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