AssemblyBuilder以及Activator雙劍合璧

AssemblyBuilder和Activator兩個類是DispatchProxy類實現動態代理以及AOP的根本,示例demo可參考 DispatchProxy實現動態代理及AOP 。AssemblyBuilder的命名空間是System.Reflection.Emit,沒錯就是你聽過的Emit。那麼它是幹什麼用的?先看看 官方 的示例代碼:html

// ↓ 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();

先看看輸出結果吧:
api

我猜您看的迷糊吧,這都啥玩意,不急。對AssemblyBuilder以及Activator的概念是:動態建立類型。上面的代碼中的AssemblyBuilder相關代碼是動態的構造一個完整的類型,包括了類的行爲(方法)、狀態(字段、屬性),構造函數等。至關於就是一個類型的定義:框架

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框架的代碼中也有這兩個類。ide

相關文章
相關標籤/搜索