我遇到了ISupportInitialize
。
我们使用从System.Windows.Form.BindingSource继承的自定义类。
现在我们需要从继承的类中增强ISupportInitialize
实现,以自动检查表单上的控件/组件,因为应尽可能减少手动工作。
问题是,接口是从microsoft明确实现的,所以我不能调用基类的BeginInit()
和EndInit()
方法,也不能覆盖它。
只是实现新方法会阻止基类像往常一样工作,因为这些方法不会被调用,是吗?
任何暗示赞赏...
答案 0 :(得分: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 :(得分:1)
你无法覆盖它,用反射器查看源代码告诉我你在这里做不了多少......你可以尝试使用所有接口的装饰器模式,但你很可能会得到卡在任何一种方式,因为这个类被框架使用,你不能控制它的使用。
无论如何,如果你想尝试一下,这就是想法:
这样的事情:
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 :(得分: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
}
}
您不必显式实现这两种方法,因为基类已经实现了它,所以如果您只对初始化后添加逻辑感兴趣,则可以省略BeginInit()
。