不具有继承关系的Delegate如何进行类型转换?
2012-11-03 10:56
585 查看
[code] static void RegisterEventHandler<T>(T target, EventHandler eventHandler)
{
EventInfo[] events = typeof(T).GetEvents();
foreach (EventInfo eventInfo in events)
{
eventInfo.AddEventHandler(target, EventHandlerConverter.Convert(eventHandler, eventInfo.EventHandlerType));
}
}
[/code]
[/code]
我们通过如下的代码定义了一个类型Foo,它具有Bar、Baz和Qux三个事件,其Delegate类分别是BarEventHandler、BazEventHandler和QuxEventHandler。当RaiseEvents方法被调用的时候,注册的三个事件被触发。
[code] [code] public class BarEventArgs : EventArgs
{}
public class BazEventArgs : EventArgs
{}
public class QuxEventArgs : EventArgs
{}
public delegate void BarEventHandler(object sender, BarEventArgs e);
public delegate void BazEventHandler(object sender, BazEventArgs e);
public delegate void QuxEventHandler(object sender, QuxEventArgs e);
public class Foo
{
public event BarEventHandler Bar;
public event BazEventHandler Baz;
public event QuxEventHandler Qux;
public void RaiseEvents()
{
if (null != Bar) Bar(this, new BarEventArgs());
if (null != Baz) Baz(this, new BazEventArgs());
if (null != Qux) Qux(this, new QuxEventArgs());
}
}
[/code]
[/code]
现在我们在Main方法中编写如下的程序。从输出结果可以看出,同一个EventHandler是否能够成功注册给Foo中不同类型的三个事件。
[code] [code] class Program
{
static void Main(string[] args)
{
Foo foo = new Foo();
RegisterEventHandler<Foo>(foo, Log);
foo.RaiseEvents();
}
static void Log(object sender, EventArgs e)
{
Console.WriteLine("{0}:{1}", sender.GetType().Name, e.GetType().Name);
}
}
[/code]
[/code]
输出结果:
[code] [code] Foo: BarEventArgs
Foo: BazEventArgs
Foo: QuxEventArgs
[/code]
[/code]
实现在EventHandlerConverter的静态方法Convert方法中的EventHandler与兼容Delegate类型之间的转换是通过“Emit”的机制实现,具体的实现逻辑如下面的代码片断所示。IsValidEventHandler方法用于验证指定的类型是否与EventHandler兼容(按照上面提及的标准进行验证),在Convert方法中我们通过Emit的方式创建了一个DynamicMethod 对象,并最终调用CreateDelegate方法将指定的Delegate对象转换成目标Delegate类型。泛型方法Convert<TDelegate>以强类型的方式指定转换的目标类型。
[code] [code] public static class EventHandlerConverter
{
public static bool IsValidEventHandler(Type eventHandlerType, out ParameterInfo[] parameters)
{
Guard.ArgumentNotNull(eventHandlerType, "eventHandlerType");
if (!typeof(Delegate).IsAssignableFrom(eventHandlerType))
{
parameters = new ParameterInfo[0];
return false;
}
MethodInfo invokeMethod = eventHandlerType.GetMethod("Invoke");
if (invokeMethod.ReturnType != typeof(void))
{
parameters = new ParameterInfo[0];
return false;
}
parameters = invokeMethod.GetParameters();
if (parameters.Length != 2 || parameters[0].ParameterType != typeof(object))
{
return false;
}
if (!typeof(EventArgs).IsAssignableFrom(parameters[1].ParameterType))
{
return false;
}
return true;
}
public static Delegate Convert(Delegate eventHandler, Type eventHandlerType)
{
Guard.ArgumentNotNull(eventHandler, "eventHandler");
Guard.ArgumentNotNull(eventHandlerType, "eventHandlerType");
ParameterInfo[] destinationParameters;
if (!IsValidEventHandler(eventHandlerType, out destinationParameters))
{
throw new InvalidOperationException();
}
if (eventHandler.GetType() == eventHandlerType)
{
return eventHandler;
}
ParameterInfo[] sourceParameters;
if (!IsValidEventHandler(eventHandler.GetType(), out sourceParameters))
{
throw new InvalidOperationException();
}
Type[] paramTypes = new Type[destinationParameters.Length + 1];
paramTypes[0] = eventHandler.GetType();
for (int i = 0; i < destinationParameters.Length; i++)
{
paramTypes[i + 1] = destinationParameters[i].ParameterType;
}
DynamicMethod method = new DynamicMethod("WrappedEventHandler", null, paramTypes);
MethodInfo invoker = paramTypes[0].GetMethod("Invoke");
ILGenerator il = method.GetILGenerator();
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Ldarg_1);
il.Emit(OpCodes.Ldarg_2);
if (!sourceParameters[1].ParameterType.IsAssignableFrom(destinationParameters[1].ParameterType))
{
il.Emit(OpCodes.Castclass, sourceParameters[1].ParameterType);
}
il.Emit(OpCodes.Call, invoker);
il.Emit(OpCodes.Ret);
return method.CreateDelegate(eventHandlerType, eventHandler);
}
public static TDelegate Convert<TDelegate>(Delegate eventHandler)
{
return (TDelegate)(object)Convert(eventHandler, typeof(TDelegate));
}
}
[/code]
[/code]
相关文章推荐
- 不具有继承关系的Delegate如何进行类型转换?
- Delegate如何进行类型转换?
- Delegate如何进行类型转换?
- Maven项目中如何对具有继承关系的项目的jar进行统一管理
- Delegate如何进行类型转换?
- JavaScript如何进行类型转换
- 如何在各种字符串类型之间进行转换(VS2010)
- 如何:在各种字符串类型之间进行转换
- cv::Mat与iplimage类型如何进行互相转换
- (转)Visual C++ 如何:在各种字符串类型之间进行转换
- 如何:在各种字符串类型之间进行转换(zz)
- 类型转换,类与类之间的转换,继承关系,继承与静态变量,子类父类重名,多继承,虚基类
- 【转载】如何:在各种字符串类型之间进行转换
- C++ 如何:在各种字符串类型之间进行转换
- Node.js 和 C++ 之间如何进行类型转换?
- Visual C++ 如何:在各种字符串类型之间进行转换
- cv::Mat与iplimage类型如何进行互相转换
- 存在继承关系的Java类对象之间的类型转换
- 如何实现将String类型数组转换成int类型 并进行排序
- Visual C++ 如何:在各种字符串类型之间进行转换