Exemplo n.º 1
0
        /// <summary>
        /// If a proxy type has not been generated yet, generates a proxy type that implements
        /// TInterface and forwards calls to an object of the type given in the constructor.
        /// </summary>
        private void GenerateProxyType()
        {
            if (m_ProxyType == null)
            {
                AppDomain       domain   = Thread.GetDomain();
                AssemblyBuilder assembly = domain.DefineDynamicAssembly(new AssemblyName("DuckProxy_" + typeof(TInterface).FullName.Replace(".", "_") + "_" + m_DuckType.FullName.Replace(".", "_")), AssemblyBuilderAccess.Run);
                ModuleBuilder   module   = assembly.DefineDynamicModule("DuckProxy");

                TypeBuilder proxyType = module.DefineType("DuckProxy");
                proxyType.AddInterfaceImplementation(typeof(IDuckProxy));
                proxyType.AddInterfaceImplementation(typeof(TInterface));

                // Define private field to hold a reference to the duck object to forward calls to.
                FieldBuilder duckField = proxyType.DefineField("m_Duck", m_DuckType, FieldAttributes.Private);

                // Define private .ctor(duckType duck)
                ConstructorBuilder constructor   = proxyType.DefineConstructor(MethodAttributes.Private, CallingConventions.HasThis, new Type[] { m_DuckType });
                ILGenerator        constructorIL = constructor.GetILGenerator();
                constructorIL.Emit(OpCodes.Ldarg_0);
                constructorIL.Emit(OpCodes.Ldarg_1);
                constructorIL.Emit(OpCodes.Stfld, duckField);
                constructorIL.Emit(OpCodes.Ret);

                // Define public static TInterface Wrap(object duck)
                MethodBuilder wrapMethod   = proxyType.DefineMethod("Wrap", MethodAttributes.Public | MethodAttributes.Static, CallingConventions.Standard, typeof(TInterface), new Type[] { typeof(object) });
                ILGenerator   wrapMethodIL = wrapMethod.GetILGenerator();
                wrapMethodIL.Emit(OpCodes.Ldarg_0);
                if (m_DuckType.IsValueType)
                {
                    wrapMethodIL.Emit(OpCodes.Box, m_DuckType);
                }
                wrapMethodIL.Emit(OpCodes.Newobj, constructor);
                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, duckField);
                if (m_DuckType.IsValueType)
                {
                    unwrapMethodIL.Emit(OpCodes.Box, m_DuckType);
                }
                unwrapMethodIL.Emit(OpCodes.Ret);

                // Define all members of TInterface
                MemberInfo[]          members      = typeof(TInterface).GetMembers();
                ProxyMemberDictionary proxyMembers = new ProxyMemberDictionary();
                foreach (MemberInfo member in members)
                {
                    ImplementMember(proxyType, proxyMembers, duckField, member);
                }

                m_ProxyType = proxyType.CreateType();
                m_WrapDuck  = (WrapDuckDelegate)(Delegate.CreateDelegate(typeof(WrapDuckDelegate), m_ProxyType, wrapMethod.Name));
            }
        }
Exemplo n.º 2
0
        /// <summary>
        /// If a proxy type has not been generated yet, generates a proxy type that defines a method
        /// matching the method signature of the to delegate type given in the constructor which forwards
        /// calls to a delegate of the from type given in the constructor.
        /// </summary>
        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
            }
        }
Exemplo n.º 3
0
        /// <summary>
        /// If a proxy type has not been generated yet, generates a proxy type that defines a method 
        /// matching the method signature of the to delegate type given in the constructor which forwards 
        /// calls to a delegate of the from type given in the constructor.
        /// </summary>
        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
            }
        }
Exemplo n.º 4
0
        /// <summary>
        /// If a proxy type has not been generated yet, generates a proxy type that implements
        /// the interface type given in the constructor and forwards calls to an object of the
        /// duck type given in the constructor.
        /// </summary>
        private void GenerateProxyType()
        {
            if (m_ProxyType == null)
            {
                AssemblyBuilderAccess assemblyBuilderAccess;

#if !DEBUG
                assemblyBuilderAccess = AssemblyBuilderAccess.Run;
#else
                assemblyBuilderAccess = AssemblyBuilderAccess.RunAndSave;
#endif

                AppDomain       domain       = Thread.GetDomain();
                string          assemblyName = "DuckInterfaceProxy_" + m_InterfaceType.Name.Replace(".", "_").Replace("+", "-") + "_" + m_DuckType.Name.Replace(".", "_").Replace("+", "-") + ".dll";
                AssemblyBuilder assembly     = domain.DefineDynamicAssembly(new AssemblyName(assemblyName), assemblyBuilderAccess);
                ModuleBuilder   module       = assembly.DefineDynamicModule(assemblyName);

                TypeBuilder proxyType = module.DefineType("DuckProxy");
                proxyType.AddInterfaceImplementation(typeof(IDuckProxy));
                proxyType.AddInterfaceImplementation(m_InterfaceType);

                FieldBuilder duckField;

                ConstructorBuilder constructor;
                ILGenerator        constructorIL;

                MethodBuilder wrapMethod;

                if (!m_IsDuckStatic)
                {
                    // Define private field to hold a reference to the duck object to forward calls to.
                    duckField = proxyType.DefineField("m_Duck", m_DuckType, FieldAttributes.Private);

                    // Define private .ctor(duckType duck)
                    constructor   = proxyType.DefineConstructor(MethodAttributes.Private, CallingConventions.HasThis, new Type[] { m_DuckType });
                    constructorIL = constructor.GetILGenerator();
                    constructorIL.Emit(OpCodes.Ldarg_0);
                    constructorIL.Emit(OpCodes.Ldarg_1);
                    constructorIL.Emit(OpCodes.Stfld, duckField);
                    // constructorIL is passed to other methods so that they can add code to the constructor.
                    // constructorIL.Emit(OpCodes.Ret); - This code should appear below after other methods are called.

                    // Define public static object Wrap(object duck)
                    wrapMethod = proxyType.DefineMethod("Wrap", MethodAttributes.Public | MethodAttributes.Static, CallingConventions.Standard, typeof(object), new Type[] { typeof(object) });
                    ILGenerator wrapMethodIL = wrapMethod.GetILGenerator();
                    wrapMethodIL.Emit(OpCodes.Ldarg_0);
                    if (m_DuckType.IsValueType)
                    {
                        wrapMethodIL.Emit(OpCodes.Box, m_DuckType);
                    }
                    wrapMethodIL.Emit(OpCodes.Newobj, constructor);
                    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, duckField);
                    if (m_DuckType.IsValueType)
                    {
                        unwrapMethodIL.Emit(OpCodes.Box, m_DuckType);
                    }
                    unwrapMethodIL.Emit(OpCodes.Ret);

                    // Override public bool Equals() method
                    MethodBuilder equalsMethod       = proxyType.DefineMethod("Equals", MethodAttributes.Public | MethodAttributes.Virtual, CallingConventions.HasThis, typeof(bool), new Type[] { typeof(object) });
                    MethodInfo    objectEqualsMethod = typeof(object).GetMethod("Equals", new Type[] { typeof(object) });
                    proxyType.DefineMethodOverride(equalsMethod, objectEqualsMethod);
                    ILGenerator equalsMethodIL = equalsMethod.GetILGenerator();
                    equalsMethodIL.Emit(OpCodes.Ldarg_0);
                    equalsMethodIL.Emit(OpCodes.Ldfld, duckField);
                    equalsMethodIL.Emit(OpCodes.Ldarg_1);
                    equalsMethodIL.Emit(OpCodes.Call, typeof(DuckTyping).GetMethod("Uncast", new Type[] { typeof(object) }));
                    equalsMethodIL.Emit(OpCodes.Callvirt, objectEqualsMethod);
                    equalsMethodIL.Emit(OpCodes.Ret);

                    // Override public int GetHashCode() method
                    MethodBuilder getHashCodeMethod       = proxyType.DefineMethod("GetHashCode", MethodAttributes.Public | MethodAttributes.Virtual, CallingConventions.HasThis, typeof(int), new Type[0]);
                    MethodInfo    objectGetHashCodeMethod = typeof(object).GetMethod("GetHashCode", new Type[0]);
                    proxyType.DefineMethodOverride(getHashCodeMethod, objectGetHashCodeMethod);
                    ILGenerator getHashCodeMethodIL = getHashCodeMethod.GetILGenerator();
                    getHashCodeMethodIL.Emit(OpCodes.Ldarg_0);
                    getHashCodeMethodIL.Emit(OpCodes.Ldfld, duckField);
                    getHashCodeMethodIL.Emit(OpCodes.Callvirt, objectGetHashCodeMethod);
                    getHashCodeMethodIL.Emit(OpCodes.Ret);

                    // Override string ToString() method
                    MethodBuilder toStringMethod       = proxyType.DefineMethod("ToString", MethodAttributes.Public | MethodAttributes.Virtual, CallingConventions.HasThis, typeof(string), new Type[0]);
                    MethodInfo    objectToStringMethod = typeof(object).GetMethod("ToString", new Type[0]);
                    proxyType.DefineMethodOverride(toStringMethod, objectToStringMethod);
                    ILGenerator toStringMethodIL = toStringMethod.GetILGenerator();
                    toStringMethodIL.Emit(OpCodes.Ldarg_0);
                    toStringMethodIL.Emit(OpCodes.Ldfld, duckField);
                    toStringMethodIL.Emit(OpCodes.Callvirt, objectToStringMethod);
                    toStringMethodIL.Emit(OpCodes.Ret);
                }
                else
                {
                    duckField = null;

                    // Define public .ctor()
                    constructor   = proxyType.DefineConstructor(MethodAttributes.Public, CallingConventions.HasThis, new Type[0]);
                    constructorIL = constructor.GetILGenerator();

                    wrapMethod = null;

                    // 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.Ldnull);
                    unwrapMethodIL.Emit(OpCodes.Ret);
                }

                // Define all members of m_InterfaceType
                ProxyMemberDictionary proxyMembers = new ProxyMemberDictionary();
                ImplementInterface(proxyType, proxyMembers, duckField, constructorIL, m_InterfaceType);

                // Now that we are done implementing members, finish constructor method body:
                constructorIL.Emit(OpCodes.Ret);

                // Bake it
                m_ProxyType = proxyType.CreateType();

                if (!m_IsDuckStatic)
                {
                    m_WrapDuck = (WrapDuckDelegate)(Delegate.CreateDelegate(typeof(WrapDuckDelegate), m_ProxyType, wrapMethod.Name));
                }
                else
                {
                    m_StaticProxy = Activator.CreateInstance(m_ProxyType);
                }

//#if DEBUG
                // If we're in debug mode, save the assembly so we can disassemble it if we want.
                //assembly.Save(assemblyName);
//#endif
            }
        }