private void GenerateProxyType()
{
if (m_ProxyType == null)
{
if (!CanProxy())
{
throw new ArgumentException(m_FromDelegateType.FullName + " is not compatible with " + m_ToDelegateType.FullName + ".");
}
AssemblyBuilderAccess assemblyBuilderAccess;
//#if !DEBUG
assemblyBuilderAccess = AssemblyBuilderAccess.Run;
//#else
//assemblyBuilderAccess = AssemblyBuilderAccess.RunAndSave;
//#endif
AppDomain domain = Thread.GetDomain();
string assemblyName = "DuckDelegateProxy_" + m_ToDelegateType.Name.Replace(".", "_").Replace("+", "-") + "_" + m_FromDelegateType.Name.Replace(".", "_").Replace("+", "-") + ".dll";
AssemblyBuilder assembly = domain.DefineDynamicAssembly(new AssemblyName(assemblyName), assemblyBuilderAccess);
ModuleBuilder module = assembly.DefineDynamicModule(assemblyName);
TypeBuilder proxyType = module.DefineType("DuckDelegateProxy");
proxyType.AddInterfaceImplementation(typeof(IDuckProxy));
// Define private field to hold a reference to the duck delegate to forward calls to.
FieldBuilder duckDelegateField = proxyType.DefineField("m_DuckDelegate", m_FromDelegateType, FieldAttributes.Private);
// Define private .ctor(duckDelegateType duckDelegate)
ConstructorBuilder constructor = proxyType.DefineConstructor(MethodAttributes.Private, CallingConventions.HasThis, new Type[] { m_FromDelegateType });
ILGenerator constructorIL = constructor.GetILGenerator();
constructorIL.Emit(OpCodes.Ldarg_0);
constructorIL.Emit(OpCodes.Ldarg_1);
constructorIL.Emit(OpCodes.Stfld, duckDelegateField);
constructorIL.Emit(OpCodes.Ret);
// Define Invoke method
MethodBuilder invokeMethod = ImplementInvokeMethod(proxyType, duckDelegateField);
// Define public static Delegate Wrap(Delegate duck)
MethodBuilder wrapMethod = proxyType.DefineMethod("Wrap", MethodAttributes.Public | MethodAttributes.Static, CallingConventions.Standard, typeof(Delegate), new Type[] { typeof(Delegate) });
ILGenerator wrapMethodIL = wrapMethod.GetILGenerator();
wrapMethodIL.Emit(OpCodes.Ldarg_0);
wrapMethodIL.Emit(OpCodes.Newobj, constructor);
wrapMethodIL.Emit(OpCodes.Ldftn, invokeMethod);
wrapMethodIL.Emit(OpCodes.Newobj, m_ToDelegateType.GetConstructor(new Type[] { typeof(object), typeof(IntPtr) }));
wrapMethodIL.Emit(OpCodes.Ret);
// Define public object UnwrapDuck() - Implementation of IDuckProxy
MethodBuilder unwrapMethod = proxyType.DefineMethod("UnwrapDuck", MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.Final, CallingConventions.HasThis, typeof(object), new Type[0]);
ILGenerator unwrapMethodIL = unwrapMethod.GetILGenerator();
unwrapMethodIL.Emit(OpCodes.Ldarg_0);
unwrapMethodIL.Emit(OpCodes.Ldfld, duckDelegateField);
unwrapMethodIL.Emit(OpCodes.Ret);
// Bake it
m_ProxyType = proxyType.CreateType();
m_WrapDuck = (WrapDuckDelegate)(Delegate.CreateDelegate(typeof(WrapDuckDelegate), m_ProxyType, wrapMethod.Name));
m_InvokeMethod = m_ProxyType.GetMethod("Invoke");
//#if DEBUG
// If we're in debug mode, save the assembly so we can disassemble it if we want.
//assembly.Save(assemblyName);
//#endif
}
}