vendredi 10 janvier 2020

How to emit and call an event in c# with reflection?

I am trying to create an event at runtime with reflection and trying to invoke it before an operation. Something like INotifyPropertyChanged. But i cant invoke my event. I want it to call subscibed methods, in this case Boss1.HeardIt() and print "I Heard you buddy" to screen. What am i doing wrong and how can i do it?

enter code using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Text;
using System.Threading.Tasks;

namespace StackOverflowSoru
{

public delegate void SomeththingHappenedEventHandler();
public interface Iperson
{

    void Work(string message);

    event SomeththingHappenedEventHandler SomeththingHappened;
}
public class person : Iperson
{
    public event SomeththingHappenedEventHandler SomeththingHappened;

    public void Work(string thework)
    {
        Console.WriteLine("Working on: {0}", thework);
    }

}
class Boss
{
    public void HeardIt()
    {
        Console.WriteLine("I Heard you buddy");
    }
}
class Program
{
    static Type CreateDynamicProxyType()
    {
        var assemblyName = new AssemblyName("MyProxies");
        var assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(
                   assemblyName,
                   AssemblyBuilderAccess.Run);
        var modBuilder = assemblyBuilder.DefineDynamicModule("MyProxies");

        // public class person
        // {
        var typeBuilder = modBuilder.DefineType(
            "mypersonproxy",
            TypeAttributes.Public | TypeAttributes.Class,
            typeof(object),
            new[] { typeof(Iperson) });

        //      private person _realObject;
        var fieldBuilder = typeBuilder.DefineField(
            "_realObject",
            typeof(person),
            FieldAttributes.Private);
        //event
        var field = typeBuilder.DefineField("SomeththingHappened", typeof(SomeththingHappenedEventHandler), FieldAttributes.Private);
        var eventInfo = typeBuilder.DefineEvent("SomeththingHappened", EventAttributes.None, typeof(SomeththingHappenedEventHandler));

        //add
        var addMethod = typeBuilder.DefineMethod("add_SomeththingHappened",
        MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.SpecialName | MethodAttributes.Final | MethodAttributes.HideBySig | MethodAttributes.NewSlot,
        CallingConventions.Standard | CallingConventions.HasThis,
        typeof(void),
        new[] { typeof(SomeththingHappenedEventHandler) });
        var generator = addMethod.GetILGenerator();
        var combine = typeof(Delegate).GetMethod("Combine", new[] { typeof(Delegate), typeof(Delegate) });
        generator.Emit(OpCodes.Ldarg_0);
        generator.Emit(OpCodes.Ldarg_0);
        generator.Emit(OpCodes.Ldfld, field);
        generator.Emit(OpCodes.Ldarg_1);
        generator.Emit(OpCodes.Call, combine);
        generator.Emit(OpCodes.Castclass, typeof(SomeththingHappenedEventHandler));
        generator.Emit(OpCodes.Stfld, field);
        generator.Emit(OpCodes.Ret);
        eventInfo.SetAddOnMethod(addMethod);

        //remove
        var removeMethod = typeBuilder.DefineMethod("remove_SomeththingHappened",
        MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.SpecialName | MethodAttributes.Final | MethodAttributes.HideBySig | MethodAttributes.NewSlot,
        CallingConventions.Standard | CallingConventions.HasThis,
        typeof(void),
        new[] { typeof(SomeththingHappenedEventHandler) });
        var remove = typeof(Delegate).GetMethod("Remove", new[] { typeof(Delegate), typeof(Delegate) });
        var removator = removeMethod.GetILGenerator();
        removator.Emit(OpCodes.Ldarg_0);
        removator.Emit(OpCodes.Ldarg_0);
        removator.Emit(OpCodes.Ldfld, field);
        removator.Emit(OpCodes.Ldarg_1);
        removator.Emit(OpCodes.Call, remove);
        removator.Emit(OpCodes.Castclass, typeof(SomeththingHappenedEventHandler));
        removator.Emit(OpCodes.Stfld, field);
        removator.Emit(OpCodes.Ret);
        eventInfo.SetRemoveOnMethod(removeMethod);

        //      public mypersonproxy(person arg1)
        //      {
        var constructorBuilder = typeBuilder.DefineConstructor(
            MethodAttributes.Public,
            CallingConventions.HasThis,
            new[] { typeof(person) });
        var contructorIl = constructorBuilder.GetILGenerator();
        contructorIl.Emit(OpCodes.Ldarg_0);
        contructorIl.Emit(OpCodes.Ldarg_1);
        contructorIl.Emit(OpCodes.Stfld, fieldBuilder);
        contructorIl.Emit(OpCodes.Ret);
        //      }

        //      public void Work(string arg1)
        //      {
        var methodBuilder = typeBuilder.DefineMethod("Work",
            MethodAttributes.Public | MethodAttributes.Virtual,
            typeof(void),
            new[] { typeof(string) });
        typeBuilder.DefineMethodOverride(methodBuilder,
            typeof(Iperson).GetMethod("Work"));
        var tweetIl = methodBuilder.GetILGenerator();

        //          Console.WriteLine("Hello before!");
        tweetIl.Emit(OpCodes.Ldstr, "Hello before!");
        tweetIl.Emit(OpCodes.Call, typeof(Console)
            .GetMethod("WriteLine", new[] { typeof(string) }));

        //raise probably something wrong here
        var eventmethodBuilder = typeBuilder.DefineMethod("OnSomeththingHappened",
        MethodAttributes.Family | MethodAttributes.Virtual | MethodAttributes.HideBySig | MethodAttributes.NewSlot,
        typeof(void),
        new[] { typeof(string) });
        var methodgenerator = eventmethodBuilder.GetILGenerator();

        var returnLabel = methodgenerator.DefineLabel();

        var eventArgsCtor = typeof(PropertyChangedEventArgs).GetConstructor(new[] { typeof(string) });

        methodgenerator.DeclareLocal(typeof(PropertyChangedEventHandler));

        methodgenerator.Emit(OpCodes.Ldarg_0);
        methodgenerator.Emit(OpCodes.Ldfld, field); 
        methodgenerator.Emit(OpCodes.Stloc_0);
        methodgenerator.Emit(OpCodes.Ldloc_0);
        methodgenerator.Emit(OpCodes.Brfalse, returnLabel);
        methodgenerator.Emit(OpCodes.Ldloc_0);
        methodgenerator.Emit(OpCodes.Ldarg_0);
        methodgenerator.Emit(OpCodes.Ldarg_1);

        methodgenerator.Emit(OpCodes.Newobj, eventArgsCtor);
        methodgenerator.Emit(OpCodes.Callvirt, typeof(PropertyChangedEventHandler).GetMethod("Invoke"));
        methodgenerator.MarkLabel(returnLabel);
        methodgenerator.Emit(OpCodes.Ret);

        eventInfo.SetRaiseMethod(eventmethodBuilder);



        //          _realObject.Work(arg1);
        tweetIl.Emit(OpCodes.Ldarg_0);
        tweetIl.Emit(OpCodes.Ldfld, fieldBuilder);
        tweetIl.Emit(OpCodes.Ldarg_1);
        tweetIl.Emit(OpCodes.Call,
            fieldBuilder.FieldType.GetMethod("Work"));

        //          Console.WriteLine("Hello after!");
        tweetIl.Emit(OpCodes.Ldstr, "Hello after!");
        tweetIl.Emit(OpCodes.Call, typeof(Console)
            .GetMethod("WriteLine", new[] { typeof(string) }));
        tweetIl.Emit(OpCodes.Ret);
        //      }
        // }


        return typeBuilder.CreateType();
    }

        static void Main(string[] args)
    {
        Boss boss1 = new Boss();

        var type = CreateDynamicProxyType();

        var dynamicProxy = (Iperson)Activator.CreateInstance(
            type, new object[] { new person() });

        dynamicProxy.SomeththingHappened += boss1.HeardIt;

        dynamicProxy.Work("fill the excel documents");
    }

}
}




Aucun commentaire:

Enregistrer un commentaire