2011-05-05 59 views
4

我被困在與ISupportInitialize點。如何正確覆蓋ISupportInitialize實現

我們使用從System.Windows.Form.BindingSource繼承的自定義類。 現在我們需要增強我們繼承的類中的ISupportInitialize實現,以便自動檢查表單上的控件/組件,因爲應該儘可能地減少手動工作。

問題是,接口是明確從微軟實施,所以我不能調用BeginInit()EndInit()基類的方法也不能覆蓋它。

只是實現新的方法會阻止基類正常工作,因爲方法不會被調用,他們會嗎?

任何暗示讚賞...

回答

1

不能覆蓋它,並尋找與反射源告訴我,你將不能夠多在這裏做...你可以嘗試使用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) 
} 

同樣,這要依賴於所有的客戶端代碼(也在框架)要經過的接口,這是我不會把錢。

2

這是一個非常有趣的問題!

在我看來,調用基類中明確實現的方法的唯一方法是使用反射。這樣的事情應該做的工作(未經測試):

public class YourBindingSource : BindingSource, ISupportInitialize 
{ 
    public void BeginInit() 
    { 
     Type baseType = base.GetType(); 
     InterfaceMapping interfaceMapping = baseType.GetInterfaceMap(typeof(ISupportInitialize)); 

     foreach(MethodInfo targetMethod in interfaceMapping.TargetMethods) 
     { 
      bool isBeginInitMethod = ...; // Could be determined by checking the name.. 
      if(isBeginInitMethod) 
      { 
       targetMethod.Invoke(this, new object[0]); 
      } 
     } 
    } 
} 
1

我用一對夫婦的擴展方法來實現這一目標:

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; 
    } 
} 

在你的類,明確實施ISupportInitialize並調用相應的擴展方法,例如:

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

     // More begin init logic 
    } 

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

     // More end init logic 
    } 
} 

您不必明確實現這兩種方法,因爲基類已經實現了,所以如果你只添加感興趣的LO gic初始化後,你可以省略BeginInit()