AssemblyBuilder以及Activator双剑合璧

2023-10-19 19:33:03 浏览数 (2)

AssemblyBuilder和Activator两个类是DispatchProxy类实现动态代理以及AOP的根本,示例demo可参考 DispatchProxy实现动态代理及AOP 。AssemblyBuilder的命名空间是System.Reflection.Emit,没错就是你听过的Emit。那么它是干什么用的?先看看 官方 的示例代码:

代码语言:javascript复制
// ↓ AssemblyBuilder构造自定义类
AssemblyName aName = new AssemblyName("DynamicAssemblyExample");
AssemblyBuilder ab =
    AssemblyBuilder.DefineDynamicAssembly(
        aName,
        AssemblyBuilderAccess.Run);

ModuleBuilder mb =
    ab.DefineDynamicModule(aName.Name);

TypeBuilder tb = mb.DefineType(
    "MyDynamicType",
     TypeAttributes.Public);

FieldBuilder fbNumber = tb.DefineField(
    "m_number",
    typeof(int),
    FieldAttributes.Private);

Type[] parameterTypes = { typeof(int) };
ConstructorBuilder ctor1 = tb.DefineConstructor(
    MethodAttributes.Public,
    CallingConventions.Standard,
    parameterTypes);

ILGenerator ctor1IL = ctor1.GetILGenerator();
ctor1IL.Emit(OpCodes.Ldarg_0);
ctor1IL.Emit(OpCodes.Call,
    typeof(object).GetConstructor(Type.EmptyTypes));
ctor1IL.Emit(OpCodes.Ldarg_0);
ctor1IL.Emit(OpCodes.Ldarg_1);
ctor1IL.Emit(OpCodes.Stfld, fbNumber);
ctor1IL.Emit(OpCodes.Ret);

ConstructorBuilder ctor0 = tb.DefineConstructor(
    MethodAttributes.Public,
    CallingConventions.Standard,
    Type.EmptyTypes);

ILGenerator ctor0IL = ctor0.GetILGenerator();
ctor0IL.Emit(OpCodes.Ldarg_0);
ctor0IL.Emit(OpCodes.Ldc_I4_S, 42);
ctor0IL.Emit(OpCodes.Call, ctor1);
ctor0IL.Emit(OpCodes.Ret);

PropertyBuilder pbNumber = tb.DefineProperty(
    "Number",
    PropertyAttributes.HasDefault,
    typeof(int),
    null);

MethodAttributes getSetAttr = MethodAttributes.Public |
    MethodAttributes.SpecialName | MethodAttributes.HideBySig;

MethodBuilder mbNumberGetAccessor = tb.DefineMethod(
    "get_Number",
    getSetAttr,
    typeof(int),
    Type.EmptyTypes);

ILGenerator numberGetIL = mbNumberGetAccessor.GetILGenerator();
numberGetIL.Emit(OpCodes.Ldarg_0);
numberGetIL.Emit(OpCodes.Ldfld, fbNumber);
numberGetIL.Emit(OpCodes.Ret);

MethodBuilder mbNumberSetAccessor = tb.DefineMethod(
    "set_Number",
    getSetAttr,
    null,
    new Type[] { typeof(int) });

ILGenerator numberSetIL = mbNumberSetAccessor.GetILGenerator();
numberSetIL.Emit(OpCodes.Ldarg_0);
numberSetIL.Emit(OpCodes.Ldarg_1);
numberSetIL.Emit(OpCodes.Stfld, fbNumber);
numberSetIL.Emit(OpCodes.Ret);

pbNumber.SetGetMethod(mbNumberGetAccessor);
pbNumber.SetSetMethod(mbNumberSetAccessor);

MethodBuilder meth = tb.DefineMethod(
    "MyMethod",
    MethodAttributes.Public,
    typeof(int),
    new Type[] { typeof(int) });

ILGenerator methIL = meth.GetILGenerator();
methIL.Emit(OpCodes.Ldarg_0);
methIL.Emit(OpCodes.Ldfld, fbNumber);
methIL.Emit(OpCodes.Ldarg_1);
methIL.Emit(OpCodes.Mul);
methIL.Emit(OpCodes.Ret);

Type t = tb.CreateType();

//↑ AssemblyBuilder类代码
MethodInfo mi = t.GetMethod("MyMethod");
PropertyInfo pi = t.GetProperty("Number");

//↓ Activator调用自定义的类
object o1 = Activator.CreateInstance(t);

Console.WriteLine("o1.Number: {0}", pi.GetValue(o1, null));
pi.SetValue(o1, 127, null);
Console.WriteLine("o1.Number: {0}", pi.GetValue(o1, null));

object[] arguments = { 22 };
Console.WriteLine("o1.MyMethod(22): {0}",
    mi.Invoke(o1, arguments));

object o2 = Activator.CreateInstance(t,
    new object[] { 5280 });
Console.WriteLine("o2.Number: {0}", pi.GetValue(o2, null));
// ↑Activator 类代码
Console.Read();

先看看输出结果吧:

我猜您看的迷糊吧,这都啥玩意,不急。对AssemblyBuilder以及Activator的概念是:动态创建类型。上面的代码中的AssemblyBuilder相关代码是动态的构造一个完整的类型,包括了类的行为(方法)、状态(字段、属性),构造函数等。相当于就是一个类型的定义:

代码语言:javascript复制
public class MyDynamicType
{
    private int m_number;

    public MyDynamicType() : this(42) {}
    public MyDynamicType(int initNumber)
    {
        m_number = initNumber;
    }

    public int Number
    {
        get { return m_number; }
        set { m_number = value; }
    }

    public int MyMethod(int multiplier)
    {
        return m_number * multiplier;
    }
}

这就是AssemblyBuilder类的作用了,那么Activator类的作用呢?其实你也应该猜到了,就是一个实例化类型及调用对象的过程。

AssemblyBuidler类 Activator类 两者的结合可以实现动态代理以及AOP,功能及其强大,园子里蒋老大的Dora AOP框架的代码中也有这两个类。

0 人点赞