• 使用反射创建动态程序集


    using System;
    using System.Net;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Documents;
    using System.Windows.Ink;
    using System.Windows.Input;
    using System.Windows.Media;
    using System.Windows.Media.Animation;
    using System.Windows.Shapes;
    using System.Reflection;
    using System.Reflection.Emit;

    namespace Emit
    {
        public class CAssemblyBuilder
        {
            public static void Demo(System.Windows.Controls.TextBlock outputBlock)
            {
                // In this version of the runtime, an assembly consists of one
                // module which contains zero or more types. This example
                // creates an assembly containing one public type named
                // "MyDynamicType". The type has a private field, a property
                // that gets and sets the private field, constructors that
                // initialize the private field, and a method that multiplies
                // a user-supplied number by the private field value and returns
                // the result. In C# the type might look like this:
                /*
                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;
                    }
                }
                */

                //完整描述程序集的唯一标识
                AssemblyName aName = new AssemblyName("DynamicAssemblyExample");

                //定义并表示动态程序集
                AssemblyBuilder ab =
                    AppDomain.CurrentDomain.DefineDynamicAssembly(
                        aName,
                        AssemblyBuilderAccess.Run);

                // 创建模块
                ModuleBuilder mb = ab.DefineDynamicModule(aName.Name);

                //类的新实例
                TypeBuilder tb = mb.DefineType(
                    "MyDynamicClassName",
                     TypeAttributes.Public);

                // 添加字段 type int (Int32).
                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();
                // For a constructor, argument zero is a reference to the new
                // instance. Push it on the stack before calling the base
                // class constructor. Specify the default constructor of the
                // base class (System.Object) by passing an empty array of
                // types (Type.EmptyTypes) to GetConstructor.
                ctor1IL.Emit(OpCodes.Ldarg_0);
                ctor1IL.Emit(OpCodes.Call,
                    typeof(object).GetConstructor(Type.EmptyTypes));
                // Push the instance on the stack before pushing the argument
                // that is to be assigned to the private field m_number.
                ctor1IL.Emit(OpCodes.Ldarg_0);
                ctor1IL.Emit(OpCodes.Ldarg_1);
                ctor1IL.Emit(OpCodes.Stfld, fbNumber);
                ctor1IL.Emit(OpCodes.Ret);

                // Define a default constructor that supplies a default value
                // for the private field. For parameter types, pass the empty
                // array of types or pass null.
                ConstructorBuilder ctor0 = tb.DefineConstructor(
                    MethodAttributes.Public,
                    CallingConventions.Standard,
                    Type.EmptyTypes);

                ILGenerator ctor0IL = ctor0.GetILGenerator();
                // For a constructor, argument zero is a reference to the new
                // instance. Push it on the stack before pushing the default
                // value on the stack, then call constructor ctor1.
                ctor0IL.Emit(OpCodes.Ldarg_0);
                ctor0IL.Emit(OpCodes.Ldc_I4_S, 42);
                ctor0IL.Emit(OpCodes.Call, ctor1);
                ctor0IL.Emit(OpCodes.Ret);

                // Define a property named Number that gets and sets the private
                // field.
                //
                // The last argument of DefineProperty is null, because the
                // property has no parameters. (If you don't specify null, you must
                // specify an array of Type objects. For a parameterless property,
                // use the built-in array with no elements: Type.EmptyTypes)
                PropertyBuilder pbNumber = tb.DefineProperty(
                    "Number",
                    PropertyAttributes.HasDefault,
                    typeof(int),
                    null);

                // The property "set" and property "get" methods require a special
                // set of attributes.
                MethodAttributes getSetAttr = MethodAttributes.Public |
                    MethodAttributes.SpecialName | MethodAttributes.HideBySig;

                // Define the "get" accessor method for Number. The method returns
                // an integer and has no arguments. (Note that null could be
                // used instead of Types.EmptyTypes)
                MethodBuilder mbNumberGetAccessor = tb.DefineMethod(
                    "get_Number",
                    getSetAttr,
                    typeof(int),
                    Type.EmptyTypes);

                ILGenerator numberGetIL = mbNumberGetAccessor.GetILGenerator();
                // For an instance property, argument zero is the instance. Load the
                // instance, then load the private field and return, leaving the
                // field value on the stack.
                numberGetIL.Emit(OpCodes.Ldarg_0);
                numberGetIL.Emit(OpCodes.Ldfld, fbNumber);
                numberGetIL.Emit(OpCodes.Ret);

                // Define the "set" accessor method for Number, which has no return
                // type and takes one argument of type int (Int32).
                MethodBuilder mbNumberSetAccessor = tb.DefineMethod(
                    "set_Number",
                    getSetAttr,
                    null,
                    new Type[] { typeof(int) });

                ILGenerator numberSetIL = mbNumberSetAccessor.GetILGenerator();
                // Load the instance and then the numeric argument, then store the
                // argument in the field.
                numberSetIL.Emit(OpCodes.Ldarg_0);
                numberSetIL.Emit(OpCodes.Ldarg_1);
                numberSetIL.Emit(OpCodes.Stfld, fbNumber);
                numberSetIL.Emit(OpCodes.Ret);

                // Last, map the "get" and "set" accessor methods to the
                // PropertyBuilder. The property is now complete.
                pbNumber.SetGetMethod(mbNumberGetAccessor);
                pbNumber.SetSetMethod(mbNumberSetAccessor);

                // Define a method that accepts an integer argument and returns
                // the product of that integer and the private field m_number. This
                // time, the array of parameter types is created on the fly.
                MethodBuilder meth = tb.DefineMethod(
                    "MyMethod",
                    MethodAttributes.Public,
                    typeof(int),
                    new Type[] { typeof(int) });

                ILGenerator methIL = meth.GetILGenerator();
                // To retrieve the private instance field, load the instance it
                // belongs to (argument zero). After loading the field, load the
                // argument one and then multiply. Return from the method with
                // the return value (the product of the two numbers) on the
                // execution stack.
                methIL.Emit(OpCodes.Ldarg_0);
                methIL.Emit(OpCodes.Ldfld, fbNumber);
                methIL.Emit(OpCodes.Ldarg_1);
                methIL.Emit(OpCodes.Mul);
                methIL.Emit(OpCodes.Ret);

                // Finish the type.
                Type t = tb.CreateType();

                // The code can be executed immediately. Start by getting reflection
                // objects for the method and the property.
                MethodInfo mi = t.GetMethod("MyMethod");
                PropertyInfo pi = t.GetProperty("Number");

                // Create an instance of MyDynamicType using the default
                // constructor.
                object o1 = Activator.CreateInstance(t);

                // Display the value of the property, then change it to 127 and
                // display it again. Use null to indicate that the property
                // has no index.
                outputBlock.Text += String.Format("o1.Number: {0}\n", pi.GetValue(o1, null));
                pi.SetValue(o1, 127, null);
                outputBlock.Text += String.Format("o1.Number: {0}\n", pi.GetValue(o1, null));

                // Call MyMethod, passing 22, and display the return value, 22
                // times 127. Arguments must be passed as an array, even when
                // there is only one.
                object[] arguments = { 22 };
                outputBlock.Text += String.Format("o1.MyMethod(22): {0}\n",
                    mi.Invoke(o1, arguments));

                // Create an instance of MyDynamicType using the constructor
                // that specifies m_Number. The constructor is identified by
                // matching the types in the argument array. In this case,
                // the argument array is created on the fly. Display the
                // property value.
                object o2 = Activator.CreateInstance(t,
                    new object[] { 5280 });
                outputBlock.Text += String.Format("o2.Number: {0}\n", pi.GetValue(o2, null));
            }

        }
    }

    关于作者: 王昕(QQ:475660) 在广州工作生活30余年。十多年开发经验,在Java、即时通讯、NoSQL、BPM、大数据等领域较有经验。
    目前维护的开源产品:https://gitee.com/475660
  • 相关阅读:
    Android NDK 环境搭建(Native Development Kit )
    No enclosing instance of type Test is accessible. Must qualify the allocation with an enclosing in
    ASP.NET 未被授权访问所请求的资源。请考虑授予 ASP.NET 请求标识访问此资源的?
    解决FileUpload控件上传文件大小限制
    学习图表控件MsChart
    Delphi PChar与String互转
    Ext.data.Store的基本用法
    My97 DatePicker 日期格式
    ASP.net流的方式输出图片或文件
    C# 二进制、十进制、十六进制互转
  • 原文地址:https://www.cnblogs.com/starcrm/p/1519248.html
Copyright © 2020-2023  润新知