public void AddOtherMethod_PInvokeImpl_Twice()
        {
            TypeBuilder   type         = Helpers.DynamicType(TypeAttributes.Abstract);
            EventBuilder  eventBuilder = type.DefineEvent("TestEvent", EventAttributes.None, typeof(TestEventHandler));
            MethodBuilder method       = type.DefineMethod("TestMethod", MethodAttributes.PinvokeImpl);

            eventBuilder.AddOtherMethod(method);
            eventBuilder.AddOtherMethod(method);
        }
예제 #2
0
        public void TestAddOtherMethodWithPInvokeMethod()
        {
            EventBuilder  ev     = TypeBuilder.DefineEvent("Event_PosTest4", EventAttributes.None, typeof(TestEventHandler));
            MethodBuilder method = TypeBuilder.DefineMethod("Method_PosTest4", MethodAttributes.PinvokeImpl);

            ev.AddOtherMethod(method);

            // add this method again
            ev.AddOtherMethod(method);
        }
예제 #3
0
        public void TestAddOtherMethodWithAbstractMethod()
        {
            EventBuilder  ev     = TypeBuilder.DefineEvent("Event_PosTest1", EventAttributes.None, typeof(TestEventHandler));
            MethodBuilder method = TypeBuilder.DefineMethod("Method_PosTest1", MethodAttributes.Abstract | MethodAttributes.Virtual);

            ev.AddOtherMethod(method);

            // add this method again
            ev.AddOtherMethod(method);
        }
예제 #4
0
        public void TestAddOtherMethodWithInstanceMethod()
        {
            EventBuilder  ev     = TypeBuilder.DefineEvent("Event_PosTest2", EventAttributes.None, typeof(TestEventHandler));
            MethodBuilder method = TypeBuilder.DefineMethod("Method_PosTest2", MethodAttributes.Public);
            ILGenerator   ilgen  = method.GetILGenerator();

            ilgen.Emit(OpCodes.Ret);
            ev.AddOtherMethod(method);

            // add this method again
            ev.AddOtherMethod(method);
        }
        public void AddOtherMethod_StaticMethod_Twice()
        {
            TypeBuilder   type         = Helpers.DynamicType(TypeAttributes.Abstract);
            EventBuilder  eventBuilder = type.DefineEvent("TestEvent", EventAttributes.None, typeof(TestEventHandler));
            MethodBuilder method       = type.DefineMethod("TestMethod", MethodAttributes.Static);
            ILGenerator   ilGenerator  = method.GetILGenerator();

            ilGenerator.Emit(OpCodes.Ret);

            eventBuilder.AddOtherMethod(method);
            eventBuilder.AddOtherMethod(method);
        }
예제 #6
0
        public void TestAddOtherMethodWithStaticMethod()
        {
            byte[] bytes = new byte[MethodBodyLength];
            TestLibrary.Generator.GetBytes(bytes);
            EventBuilder  ev     = TypeBuilder.DefineEvent("Event_PosTest3", EventAttributes.None, typeof(TestEventHandler));
            MethodBuilder method = TypeBuilder.DefineMethod("Method_PosTest3", MethodAttributes.Static);
            ILGenerator   ilgen  = method.GetILGenerator();

            ilgen.Emit(OpCodes.Ret);

            ev.AddOtherMethod(method);

            // add this method again
            ev.AddOtherMethod(method);
        }
예제 #7
0
        /// <summary>
        /// Implements an interface event in a duck proxy type using a given type builder.
        /// If successful, the implemented event will be added to the given proxy member dictionary.
        /// </summary>
        /// <param name="proxyType">Type builder for the duck proxy type.</param>
        /// <param name="proxyMembers">Dictionary of members of the proxy type.</param>
        /// <param name="duckField">Field that holds a reference to the duck object to forward calls to.</param>
        /// <param name="interfaceEvent">The interface event to implement.</param>
        private void ImplementEvent(TypeBuilder proxyType, ProxyMemberDictionary proxyMembers, FieldInfo duckField, EventInfo interfaceEvent)
        {
            EventInfo duckEvent = FindDuckEvent(interfaceEvent);

            if (duckEvent == null)
            {
                throw new NotImplementedException("Duck type does not implement an event named \"" + interfaceEvent.Name + "\" with the same event handler type.");
            }

            EventBuilder proxyEvent = proxyType.DefineEvent(interfaceEvent.Name, EventAttributes.None, interfaceEvent.EventHandlerType);

            // Associated methods appear before the event in the member array; thus, they have already been
            // defined and implemented.  The proxy member dictionary is used to refer to these.
            proxyEvent.SetAddOnMethod((MethodBuilder)(proxyMembers[duckEvent.GetAddMethod()]));
            proxyEvent.SetRemoveOnMethod((MethodBuilder)(proxyMembers[duckEvent.GetRemoveMethod()]));
            proxyEvent.SetRaiseMethod((MethodBuilder)(proxyMembers[duckEvent.GetRaiseMethod()]));
            MethodInfo[] otherDuckMethods = duckEvent.GetOtherMethods();
            foreach (MethodInfo otherDuckMethod in otherDuckMethods)
            {
                if (proxyMembers.ContainsKey(otherDuckMethod))
                {
                    proxyEvent.AddOtherMethod((MethodBuilder)(proxyMembers[otherDuckMethod]));
                }
            }

            // Add proxy event to the proxy member dictionary
            // (This is not really necessary, but good to keep things consistent)
            // proxyMembers.Add(duckEvent, proxyEvent);
            // For some reason, EventBuilder does not inherit MemberInfo, so it cannot be added.
        }
        public void AddOtherMethod_NullMethod_ThrowsArgumentNullException()
        {
            TypeBuilder  type         = Helpers.DynamicType(TypeAttributes.Abstract);
            EventBuilder eventBuilder = type.DefineEvent("TestEvent", EventAttributes.None, typeof(TestEventHandler));

            AssertExtensions.Throws <ArgumentNullException>("mdBuilder", () => eventBuilder.AddOtherMethod(null));
        }
예제 #9
0
        public void TestCreation()
        {
            eb = tb.DefineEvent("event2", EventAttributes.SpecialName, typeof(AnEvent));

            eb.SetRaiseMethod(mb);
            eb.SetAddOnMethod(mb);
            eb.SetRemoveOnMethod(mb);
            eb.AddOtherMethod(mb);
            eb.AddOtherMethod(mb);

            Type t = tb.CreateType();

            MethodInfo mi = t.GetMethod("OnAnEvent");

            EventInfo[] events = t.GetEvents();
            Assert.AreEqual(2, events.Length);

            {
                EventInfo ev = t.GetEvent("event1");
                Assert.AreEqual("event1", ev.Name);
                Assert.AreEqual(EventAttributes.None, ev.Attributes);
                Assert.AreEqual(t, ev.DeclaringType);

                Assert.AreEqual(typeof(AnEvent), ev.EventHandlerType);
                Assert.AreEqual(true, ev.IsMulticast);
                Assert.AreEqual(false, ev.IsSpecialName);

                Assert.AreEqual(mi, ev.GetAddMethod());
                Assert.AreEqual(null, ev.GetRaiseMethod());
                Assert.AreEqual(mi, ev.GetRemoveMethod());
            }

            {
                EventInfo ev = t.GetEvent("event2");
                Assert.AreEqual("event2", ev.Name);
                Assert.AreEqual(EventAttributes.SpecialName, ev.Attributes);
                Assert.AreEqual(t, ev.DeclaringType);

                Assert.AreEqual(typeof(AnEvent), ev.EventHandlerType);
                Assert.AreEqual(true, ev.IsMulticast);
                Assert.AreEqual(true, ev.IsSpecialName);

                Assert.AreEqual(mi, ev.GetAddMethod());
                Assert.AreEqual(mi, ev.GetRaiseMethod());
                Assert.AreEqual(mi, ev.GetRemoveMethod());
            }
        }
        public void AddOtherMethod_MultipleDifferentMethods()
        {
            TypeBuilder   type         = Helpers.DynamicType(TypeAttributes.Abstract);
            EventBuilder  eventBuilder = type.DefineEvent("TestEvent", EventAttributes.None, typeof(TestEventHandler));
            MethodBuilder method1      = type.DefineMethod("PInvokeMethod", MethodAttributes.PinvokeImpl);
            MethodBuilder method2      = type.DefineMethod("PublicMethod", MethodAttributes.Public);
            ILGenerator   ilGenerator  = method2.GetILGenerator();

            ilGenerator.Emit(OpCodes.Ret);
            MethodBuilder method3 = type.DefineMethod("StaticMethod", MethodAttributes.Static);
            MethodBuilder method4 = type.DefineMethod("AbstractMethod", MethodAttributes.Abstract | MethodAttributes.Virtual);

            eventBuilder.AddOtherMethod(method1);
            eventBuilder.AddOtherMethod(method2);
            eventBuilder.AddOtherMethod(method3);
            eventBuilder.AddOtherMethod(method4);
        }
예제 #11
0
        public void TestThrowsExceptionOnCreateTypeCalled()
        {
            EventBuilder  ev     = TypeBuilder.DefineEvent("Event_NegTest2", EventAttributes.None, typeof(TestEventHandler));
            MethodBuilder method = TypeBuilder.DefineMethod("Method_NegTest2", MethodAttributes.Abstract | MethodAttributes.Virtual);

            TypeBuilder.CreateTypeInfo().AsType();

            Assert.Throws <InvalidOperationException>(() => { ev.AddOtherMethod(method); });
        }
예제 #12
0
        public void TestAddOtherMethodWithMultipleMethods()
        {
            byte[] bytes = new byte[MethodBodyLength];
            TestLibrary.Generator.GetBytes(bytes);

            EventBuilder  ev      = TypeBuilder.DefineEvent("Event_PosTest5", EventAttributes.None, typeof(TestEventHandler));
            MethodBuilder method1 = TypeBuilder.DefineMethod("PMethod_PosTest5", MethodAttributes.PinvokeImpl);
            MethodBuilder method2 = TypeBuilder.DefineMethod("IMethod_PosTest5", MethodAttributes.Public);
            ILGenerator   ilgen   = method2.GetILGenerator();

            ilgen.Emit(OpCodes.Ret);
            MethodBuilder method3 = TypeBuilder.DefineMethod("SMethod_PosTest5", MethodAttributes.Static);
            MethodBuilder method4 = TypeBuilder.DefineMethod("AMethod_PosTest5", MethodAttributes.Abstract | MethodAttributes.Virtual);

            ev.AddOtherMethod(method1);
            ev.AddOtherMethod(method2);
            ev.AddOtherMethod(method3);
            ev.AddOtherMethod(method4);
        }
        public void AddOtherMethod_TypeCreated_ThrowsInvalidOperationException()
        {
            TypeBuilder   type         = Helpers.DynamicType(TypeAttributes.Abstract);
            EventBuilder  eventBuilder = type.DefineEvent("TestEvent", EventAttributes.None, typeof(TestEventHandler));
            MethodBuilder method       = type.DefineMethod("TestMethod", MethodAttributes.Abstract | MethodAttributes.Virtual);

            type.CreateTypeInfo().AsType();

            Assert.Throws <InvalidOperationException>(() => eventBuilder.AddOtherMethod(method));
        }
예제 #14
0
        public void TestThrowsExceptionOnNullMethod()
        {
            EventBuilder ev = TypeBuilder.DefineEvent("Event_NegTest1", EventAttributes.None, typeof(TestEventHandler));

            Assert.Throws <ArgumentNullException>(() => { ev.AddOtherMethod(null); });
        }
예제 #15
0
 public void TestAddOtherMethod1()
 {
     eb.AddOtherMethod(null);
 }
예제 #16
0
        /// <summary>
        /// Implements an interface event in a duck proxy type using a given type builder.
        /// If successful, the implemented event will be added to the given proxy member dictionary.
        /// </summary>
        /// <param name="proxyType">Type builder for the duck proxy type.</param>
        /// <param name="proxyMembers">Dictionary of members of the proxy type.</param>
        /// <param name="duckField">Field that holds a reference to the duck object to forward calls to.</param>
        /// <param name="constructorIL">IL generator to use to add code to the constructor if necessary.</param>
        /// <param name="interfaceEvent">The interface event to implement.</param>
        private void ImplementEvent(TypeBuilder proxyType, ProxyMemberDictionary proxyMembers, FieldInfo duckField, ILGenerator constructorIL, EventInfo interfaceEvent)
        {
            EventInfo duckEvent = FindDuckEvent(interfaceEvent);

            if (duckEvent == null)
            {
                throw new NotImplementedException("Duck type does not implement an event named \"" + interfaceEvent.Name + "\" with the same event handler type.");
            }

            EventBuilder proxyEvent = proxyType.DefineEvent(interfaceEvent.Name, EventAttributes.None, interfaceEvent.EventHandlerType);

            Type interfaceEventHandlerType = interfaceEvent.EventHandlerType;
            Type duckEventHandlerType      = duckEvent.EventHandlerType;

            // Define event add method
            MethodBuilder addMethod   = proxyType.DefineMethod("add_" + interfaceEvent.Name, MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.Final, CallingConventions.HasThis, typeof(void), new Type[] { interfaceEventHandlerType });
            ILGenerator   addMethodIL = addMethod.GetILGenerator();

            // Define event remove method
            MethodBuilder removeMethod   = proxyType.DefineMethod("remove_" + interfaceEvent.Name, MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.Final, CallingConventions.HasThis, typeof(void), new Type[] { interfaceEventHandlerType });
            ILGenerator   removeMethodIL = removeMethod.GetILGenerator();

            if (interfaceEventHandlerType == duckEventHandlerType)
            {
                // If the event handler types are the same, we can just forward calls to add and remove like normal.

                MethodInfo duckAddMethod = duckEvent.GetAddMethod();
                if (!duckAddMethod.IsStatic)
                {
                    addMethodIL.Emit(OpCodes.Ldarg_0);
                    addMethodIL.Emit(OpCodes.Ldfld, duckField);
                    addMethodIL.Emit(OpCodes.Ldarg_1);
                    addMethodIL.Emit(OpCodes.Callvirt, duckAddMethod);
                }
                else
                {
                    addMethodIL.Emit(OpCodes.Ldarg_1);
                    addMethodIL.Emit(OpCodes.Call, duckAddMethod);
                }

                MethodInfo duckRemoveMethod = duckEvent.GetRemoveMethod();
                if (!duckRemoveMethod.IsStatic)
                {
                    removeMethodIL.Emit(OpCodes.Ldarg_0);
                    removeMethodIL.Emit(OpCodes.Ldfld, duckField);
                    removeMethodIL.Emit(OpCodes.Ldarg_1);
                    removeMethodIL.Emit(OpCodes.Callvirt, duckRemoveMethod);
                }
                else
                {
                    removeMethodIL.Emit(OpCodes.Ldarg_1);
                    removeMethodIL.Emit(OpCodes.Call, duckRemoveMethod);
                }
            }
            else
            {
                // If the event handler types are different, we need some special behavior.  Specifically, the event handlers
                // added using the interface are kept as a seperate multicast delegate in the proxy class and an event handler
                // is added to the duck that calls the proxy event delegate.

                // Define the event multicast delegate field
                FieldBuilder eventHandlerField = proxyType.DefineField(interfaceEvent.Name, interfaceEventHandlerType, FieldAttributes.Private);

                // Implement the add method
                addMethodIL.Emit(OpCodes.Ldarg_0);
                addMethodIL.Emit(OpCodes.Ldarg_0);
                addMethodIL.Emit(OpCodes.Ldfld, eventHandlerField);
                addMethodIL.Emit(OpCodes.Ldarg_1);
                addMethodIL.Emit(OpCodes.Call, typeof(Delegate).GetMethod("Combine", new Type[] { typeof(Delegate), typeof(Delegate) }));
                addMethodIL.Emit(OpCodes.Castclass, interfaceEventHandlerType);
                addMethodIL.Emit(OpCodes.Stfld, eventHandlerField);

                // Implement the remove method
                removeMethodIL.Emit(OpCodes.Ldarg_0);
                removeMethodIL.Emit(OpCodes.Ldarg_0);
                removeMethodIL.Emit(OpCodes.Ldfld, eventHandlerField);
                removeMethodIL.Emit(OpCodes.Ldarg_1);
                removeMethodIL.Emit(OpCodes.Call, typeof(Delegate).GetMethod("Remove", new Type[] { typeof(Delegate), typeof(Delegate) }));
                removeMethodIL.Emit(OpCodes.Castclass, interfaceEventHandlerType);
                removeMethodIL.Emit(OpCodes.Stfld, eventHandlerField);

                // Set some local variables for later use...
                MethodInfo interfaceInvokeMethod = interfaceEventHandlerType.GetMethod("Invoke");
                Type[]     interfaceInvokeMethodParameterTypes = GetParameterTypes(interfaceInvokeMethod.GetParameters());

                MethodInfo duckInvokeMethod = duckEventHandlerType.GetMethod("Invoke");
                Type[]     duckInvokeMethodParameterTypes = GetParameterTypes(duckInvokeMethod.GetParameters());


                // Define the method that will serve as an event handler to the duck which will invoke the proxy's delegate
                MethodBuilder proxyInvokeMethod   = proxyType.DefineMethod("Invoke" + interfaceEvent.Name, MethodAttributes.Private | MethodAttributes.Virtual | MethodAttributes.Final, CallingConventions.HasThis, duckInvokeMethod.ReturnType, duckInvokeMethodParameterTypes);
                ILGenerator   proxyInvokeMethodIL = proxyInvokeMethod.GetILGenerator();

                // First, check if the proxy event handler is null
                Label ifEventHandlerIsNullLabel = proxyInvokeMethodIL.DefineLabel();
                proxyInvokeMethodIL.Emit(OpCodes.Ldarg_0);
                proxyInvokeMethodIL.Emit(OpCodes.Ldfld, eventHandlerField);
                proxyInvokeMethodIL.Emit(OpCodes.Ldnull);
                proxyInvokeMethodIL.Emit(OpCodes.Ceq);
                proxyInvokeMethodIL.Emit(OpCodes.Brtrue_S, ifEventHandlerIsNullLabel);

                // If the proxy event handler is not null, invoke it
                proxyInvokeMethodIL.Emit(OpCodes.Ldarg_0);
                proxyInvokeMethodIL.Emit(OpCodes.Ldfld, eventHandlerField);
                for (int i = 0; i < interfaceInvokeMethodParameterTypes.Length; i++)
                {
                    proxyInvokeMethodIL.Emit(OpCodes.Ldarg, i + 1);
                    DuckTyping.EmitCastIL(proxyInvokeMethodIL, interfaceInvokeMethodParameterTypes[i], duckInvokeMethodParameterTypes[i]);
                }
                proxyInvokeMethodIL.Emit(OpCodes.Callvirt, interfaceInvokeMethod);

                // If the proxy event handler is null, execution jumps here
                proxyInvokeMethodIL.MarkLabel(ifEventHandlerIsNullLabel);

                // Return
                proxyInvokeMethodIL.Emit(OpCodes.Ret);


                // Add code to the constructor to add the event handler to the duck.
                MethodInfo duckAddMethod = duckEvent.GetAddMethod();
                if (!duckAddMethod.IsStatic)
                {
                    constructorIL.Emit(OpCodes.Ldarg_0);
                    constructorIL.Emit(OpCodes.Ldfld, duckField);
                }
                constructorIL.Emit(OpCodes.Ldarg_0);
                constructorIL.Emit(OpCodes.Ldftn, proxyInvokeMethod);
                constructorIL.Emit(OpCodes.Newobj, duckEventHandlerType.GetConstructor(new Type[] { typeof(object), typeof(IntPtr) }));
                if (!duckAddMethod.IsStatic)
                {
                    constructorIL.Emit(OpCodes.Callvirt, duckAddMethod);
                }
                else
                {
                    constructorIL.Emit(OpCodes.Call, duckAddMethod);
                }
            }

            // Finish add method and set it for the event
            addMethodIL.Emit(OpCodes.Ret);
            proxyEvent.SetAddOnMethod(addMethod);

            // Finish remove method and set it for the event
            removeMethodIL.Emit(OpCodes.Ret);
            proxyEvent.SetRemoveOnMethod(removeMethod);

            // Other associated methods appear before the event in the member array; thus, they have already been
            // defined and implemented.  The proxy member dictionary is used to refer to these.
            MethodInfo raiseMethod = duckEvent.GetRaiseMethod();

            if (raiseMethod != null)
            {
                proxyEvent.SetRaiseMethod((MethodBuilder)(proxyMembers[raiseMethod]));
            }

            MethodInfo[] otherDuckMethods = duckEvent.GetOtherMethods();
            foreach (MethodInfo otherDuckMethod in otherDuckMethods)
            {
                if (proxyMembers.ContainsKey(otherDuckMethod))
                {
                    proxyEvent.AddOtherMethod((MethodBuilder)(proxyMembers[otherDuckMethod]));
                }
            }

            // Add proxy event to the proxy member dictionary
            // (This is not really necessary, but good to keep things consistent)
            // if (proxyMembers != null) proxyMembers[duckEvent] =  proxyEvent;
            // For some reason, EventBuilder does not inherit MemberInfo, so it cannot be added.
        }