C# 如何正确覆盖ISupportInitialize实现

C# 如何正确覆盖ISupportInitialize实现,c#,inheritance,interface,C#,Inheritance,Interface,我被ISupportInitialize卡住了 我们使用从System.Windows.Form.BindingSource继承的自定义类。 现在我们需要从继承的类中增强ISupportInitialize实现,以自动检查表单上的控件/组件,因为应该尽可能减少手动工作 问题是,该接口是从microsoft显式实现的,因此我不能调用基类的BeginInit()和EndInit()方法,也不能重写它 仅仅实现新方法就会阻止基类像往常一样工作,因为这些方法不会被调用,不是吗 任何提示都很感激…您不能覆

我被
ISupportInitialize
卡住了

我们使用从System.Windows.Form.BindingSource继承的自定义类。 现在我们需要从继承的类中增强
ISupportInitialize
实现,以自动检查表单上的控件/组件,因为应该尽可能减少手动工作

问题是,该接口是从microsoft显式实现的,因此我不能调用基类的
BeginInit()
EndInit()
方法,也不能重写它

仅仅实现新方法就会阻止基类像往常一样工作,因为这些方法不会被调用,不是吗


任何提示都很感激…

您不能覆盖它,并且通过反射器查看源告诉我您在这里做不了什么。。。您可以尝试对所有接口使用decorator模式,但很可能您会遇到任何一种情况,因为这个类由框架使用,您无法控制它的使用

无论如何,如果你想尝试一下,这里有一个想法:

  • 创建一个实现BindingSource中所有接口的类
  • 将实际BindingSource实例保留为私有字段
  • 只需将调用转发到专用字段即可实现所有接口方法
  • 对于要扩展的方法,请在调用原始方法之前或之后添加自定义逻辑
大概是这样的:

public class MyBindingSource : ISupportInitialize // + all other interfaces
{
    private BindingSource _original; // to be set in constructor

    public void BeginInit()
    {
        // custom logic goes here
        _original.BeginInit();
    }

    // ... (all other forwarding implementations)
}

同样,这将依赖于所有的客户机代码(也在框架中)来通过接口,这是我不会花钱的

这是一个非常有趣的问题

在我看来,在基类中调用显式实现的方法的唯一方法是使用反射。类似这样的东西应该可以完成工作(未经测试):


我使用了几种扩展方法来实现这一点:

public static class ISupportInitializeHelper
{
    const string BEGIN_INIT = "System.ComponentModel.ISupportInitialize.BeginInit",
                 END_INIT   = "System.ComponentModel.ISupportInitialize.EndInit";

    public static void InvokeBaseBeginInit<T>(this T obj)
        where T : ISupportInitialize
    {
        var baseType   = typeof(T).BaseType;

        var methodInfo = GetBeginInitMethodInfo(baseType);

        if (methodInfo != null)
            methodInfo.Invoke(obj, null);
    }

    static Dictionary<Type, MethodInfo> s_beginInitCache = new Dictionary<Type, MethodInfo>();

    private static MethodInfo GetBeginInitMethodInfo(Type type)
    {
        MethodInfo methodInfo;

        if (!s_beginInitCache.TryGetValue(type, out methodInfo))
        {
            methodInfo = type.GetMethod(BEGIN_INIT,
                                        BindingFlags.NonPublic |
                                        BindingFlags.Instance);

            s_beginInitCache[type] = methodInfo;
        }

        return methodInfo;
    }

    public static void InvokeBaseEndInit<T>(this T obj)
        where T : ISupportInitialize
    {
        var baseType   = typeof(T).BaseType;

        var methodInfo = GetEndInitMethodInfo(baseType);

        if (methodInfo != null)
            methodInfo.Invoke(obj, null);
    }

    static Dictionary<Type, MethodInfo> s_endInitCache = new Dictionary<Type, MethodInfo>();

    private static MethodInfo GetEndInitMethodInfo(Type type)
    {
        MethodInfo methodInfo;

        if (!s_endInitCache.TryGetValue(type, out methodInfo))
        {
            methodInfo = type.GetMethod(END_INIT,
                                        BindingFlags.NonPublic |
                                        BindingFlags.Instance);

            s_endInitCache[type] = methodInfo;
        }

        return methodInfo;
    }
}
您不必显式地实现这两个方法,因为基类已经实现了它,所以如果您只想在初始化后添加逻辑,可以省略
BeginInit()

public static class ISupportInitializeHelper
{
    const string BEGIN_INIT = "System.ComponentModel.ISupportInitialize.BeginInit",
                 END_INIT   = "System.ComponentModel.ISupportInitialize.EndInit";

    public static void InvokeBaseBeginInit<T>(this T obj)
        where T : ISupportInitialize
    {
        var baseType   = typeof(T).BaseType;

        var methodInfo = GetBeginInitMethodInfo(baseType);

        if (methodInfo != null)
            methodInfo.Invoke(obj, null);
    }

    static Dictionary<Type, MethodInfo> s_beginInitCache = new Dictionary<Type, MethodInfo>();

    private static MethodInfo GetBeginInitMethodInfo(Type type)
    {
        MethodInfo methodInfo;

        if (!s_beginInitCache.TryGetValue(type, out methodInfo))
        {
            methodInfo = type.GetMethod(BEGIN_INIT,
                                        BindingFlags.NonPublic |
                                        BindingFlags.Instance);

            s_beginInitCache[type] = methodInfo;
        }

        return methodInfo;
    }

    public static void InvokeBaseEndInit<T>(this T obj)
        where T : ISupportInitialize
    {
        var baseType   = typeof(T).BaseType;

        var methodInfo = GetEndInitMethodInfo(baseType);

        if (methodInfo != null)
            methodInfo.Invoke(obj, null);
    }

    static Dictionary<Type, MethodInfo> s_endInitCache = new Dictionary<Type, MethodInfo>();

    private static MethodInfo GetEndInitMethodInfo(Type type)
    {
        MethodInfo methodInfo;

        if (!s_endInitCache.TryGetValue(type, out methodInfo))
        {
            methodInfo = type.GetMethod(END_INIT,
                                        BindingFlags.NonPublic |
                                        BindingFlags.Instance);

            s_endInitCache[type] = methodInfo;
        }

        return methodInfo;
    }
}
public class MyBindingSource
    : BindingSource,
      ISupportInitialize
{
    void ISupportInitialize.BeginInit()
    {
        this.InvokeBaseBeginInit();

        // More begin init logic
    }

    void ISupportInitialize.EndInit()
    {
        this.InvokeBaseEndInit();

        // More end init logic
    }
}