Dynamically creating a proxy class

后端 未结 4 1279
深忆病人
深忆病人 2020-11-30 21:39

I am trying to create a proxy class dynamically. I know there are some very good frameworks out there to do this but this is purely a pet project as a learning exercise so

4条回答
  •  栀梦
    栀梦 (楼主)
    2020-11-30 21:54

    I wouldn't recommend doing this. Usually you use some well-known libraries such as Castle or EntLib. For some complicated classes it could be quite a challenge to dynamically generate a proxy. Here is an example of doing that using "Is" polymorphism. For this you have to declare all your methods in base as virtual. The way you were trying to do this ("Has") also possible, but for me looks more complicated.

    public class A
    {
        public virtual void B()
        {
            Console.WriteLine("Original method was called.");
        }
    }
    
    class Program
    {
    
        static void Main(string[] args)
        {
            // Create simple assembly to hold our proxy
            AssemblyName assemblyName = new AssemblyName();
            assemblyName.Name = "DynamicORMapper";
            AppDomain thisDomain = Thread.GetDomain();
            var asmBuilder = thisDomain.DefineDynamicAssembly(assemblyName,
                         AssemblyBuilderAccess.Run);
    
            var modBuilder = asmBuilder.DefineDynamicModule(
                         asmBuilder.GetName().Name, false);
    
            // Create a proxy type
            TypeBuilder typeBuilder = modBuilder.DefineType("ProxyA",
               TypeAttributes.Public |
               TypeAttributes.Class |
               TypeAttributes.AutoClass |
               TypeAttributes.AnsiClass |
               TypeAttributes.BeforeFieldInit |
               TypeAttributes.AutoLayout,
               typeof(A));
            MethodBuilder methodBuilder = typeBuilder.DefineMethod("B", MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.ReuseSlot);
            typeBuilder.DefineMethodOverride(methodBuilder, typeof(A).GetMethod("B"));
    
    
            // Generate a Console.Writeline() and base.B() calls.
            ILGenerator ilGenerator = methodBuilder.GetILGenerator();
            ilGenerator.Emit(OpCodes.Ldarg_0);
            ilGenerator.EmitWriteLine("We caught an invoke! B method was called.");
    
            ilGenerator.EmitCall(OpCodes.Call, typeBuilder.BaseType.GetMethod("B"), new Type[0]);
            ilGenerator.Emit(OpCodes.Ret);
    
            //Create a type and casting it to A. 
            Type type = typeBuilder.CreateType();
            A a = (A) Activator.CreateInstance(type);
    
            // Test it
            a.B();
            Console.ReadLine();
        }
    }
    

提交回复
热议问题