我正在编写一段处理 Windows 窗体控件的 C# 代码。这是一个小例子,一个小包装器,用于获取某些控件的边界矩形(在屏幕坐标中):
public class GUIObject {
protected Control m_control;
// [..]
public virtual Rectangle Bounds {
get {
Rectangle r = m_control.Bounds;
if ( m_control.Parent != null ) {
return m_control.Parent.RectangleToScreen( r );
}
return r;
}
}
}
此代码被编译成一个库,该库作为“插件”分发,以加载到客户应用程序中。然而,事实证明,一些客户在他们的应用程序中使用的 Windows 窗体版本与我的插件所链接的版本不同。我的计划是通过使上述代码后期绑定来解决这个问题,这样它就可以与当前应用程序域中加载的任何 Windows 窗体版本一起工作。在 .NET 4 中,我可以使用dynamic
关键字,但遗憾的是,这段代码也应该适用于 .NET3 应用程序。因此,我开始使用反射 API,引入了一个小助手对象,这使得使用反射 API 变得更好:
public class LateBoundObject {
private Object m_o;
// [..]
public Object GetProperty( String name ) {
PropertyInfo pi = m_o.GetType().GetProperty( name );
return pi == null ? null
: pi.GetValue( m_o, null );
}
public Object InvokeMethod( String name, Object[] args ) {
MethodInfo mi = m_o.GetType().GetMethod( name );
return mi == null ? null
: mi.Invoke( m_o, args );
}
}
public class GUIObject {
protected LateBoundObject m_control;
// [..]
public virtual Rectangle Bounds {
get {
Object r = m_control.GetProperty( "Bounds" );
if ( r == null) {
return new Rectangle();
}
Object parent = m_control.GetProperty( "Parent" );
if ( parent != null ) {
LateBoundObject po = new LateBoundObject( parent );
r = po.InvokeMethod( "RectangleToScreen",
new Object[] { r } );
}
return (Rectangle)r;
}
}
}
不是很漂亮。调用方需要进行大量转换,我怀疑我迟早也必须处理重载的方法或属性 - 前进的道路相当坎坷。理想情况下,包装对象将允许保持原始代码非常相同。
所以,在我开始修复LateBoundObject
包装类之前,我想知道:是否有其他人有使用反射 API 使 C# 代码后期绑定的经验?如果是这样,您是如何处理它以将使用原始反射 API 的痛苦降至最低 - 您是否还使用了类似的包装类,LateBoundObject
或者您是否采用了完全不同的路线?就原始代码而言,我正在寻找侵入性最小的方式。