Я работаю над фрагментом кода C #, который касается элементов управления Windows Forms. Вот небольшой пример, крошечная оболочка для получения ограничивающего прямоугольника (в экранных координатах) для некоторого элемента управления:
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 Forms, отличную от той, с которой был связан мой плагин. Мой план состоял в том, чтобы решить эту проблему, сделав вышеуказанный код с поздней привязкой, чтобы он работал с любой версией Windows Forms, загруженной в текущий домен приложения. В .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
, я задаюсь вопросом: есть ли у кого-нибудь еще опыт создания кода C # с поздним связыванием с использованием API отражения? Если да, то как вы подходили к этому, чтобы свести к минимуму боль при использовании API-интерфейсов рефлексии - вы также использовали класс-оболочку в соответствии с LateBoundObject
или вы пошли совершенно другим путем? Я ищу наименее инвазивный способ с точки зрения оригинального кода.