| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343 | using System.Reflection;using System.Reflection.Emit;namespace WCS.Core;/// <summary>///     动态创建接口实例/// </summary>/// <typeparam name="T">接口</typeparam>/// <typeparam name="TBase">基类</typeparam>public static class Generator<T, TBase> where TBase : IProtocolProxy{    private const MethodAttributes METHOD_ATTRIBUTES =        MethodAttributes.Public | MethodAttributes.NewSlot | MethodAttributes.Virtual | MethodAttributes.Final |        MethodAttributes.HideBySig;    private static readonly TypeBuilder tb;    private static readonly Type Type;    static Generator()    {        if (!typeof(T).IsInterface)            throw new Exception("T必须是interface");        if (!typeof(TBase).IsClass)            throw new Exception("TBase必须是class");        var myAssemblyName = new AssemblyName();        myAssemblyName.Name = typeof(T).Name + "_Generate";        var myAssembly = AssemblyBuilder.DefineDynamicAssembly(myAssemblyName, AssemblyBuilderAccess.RunAndCollect);        //AssemblyBuilder myAssembly = AssemblyBuilder.DefineDynamicAssembly(myAssemblyName, AssemblyBuilderAccess.RunAndSave);        var myModule = myAssembly.DefineDynamicModule("Main");        tb = myModule.DefineType(typeof(T).Name + "_Generate", TypeAttributes.Public, typeof(TBase),            new[] { typeof(T) });        InitConstructors();        InitMethods();        InitProperties();        InitEvents();        try        {            Type = tb.CreateTypeInfo().AsType(); //.CreateType();        }        catch (Exception ex)        {        }        //myAssembly.Save(typeof(T).Name + ".dll");    }    private static void InitConstructors()    {        foreach (var cons in typeof(TBase).GetConstructors())        {            var pTypes = cons.GetParameters().Select(v => v.ParameterType).ToArray();            var build = tb.DefineConstructor(cons.Attributes, CallingConventions.Standard, pTypes);            for (var i = 0; i < pTypes.Length; i++) build.DefineParameter(i + 1, ParameterAttributes.In, "p" + i);            var il = build.GetILGenerator();            il.Emit(OpCodes.Ldarg_0);            for (var i = 0; i < pTypes.Length; i++) il.Emit(OpCodes.Ldarg, i + 1);            il.Emit(OpCodes.Call, cons);            //il.Emit(OpCodes.Pop);            il.Emit(OpCodes.Ret);        }    }    private static void InitMethods()    {        var ms = GetInterfaces().SelectMany(v => v.GetMethods()).ToArray();        ms = ms.Where(v => !v.IsSpecialName).ToArray();        foreach (var m in ms) GenerateMethod(m);    }    private static void InitProperties()    {        var ps = GetInterfaces().SelectMany(v => v.GetProperties());        ps = GetMembers().OfType<PropertyInfo>();        foreach (var p in ps)        {            if (typeof(TBase).GetProperty(p.Name,                    BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) != null) continue;            var pTypes = p.GetIndexParameters().Select(v => v.ParameterType).ToArray();            var pb = tb.DefineProperty(p.Name, p.Attributes, p.PropertyType, pTypes);            if (p.CanRead)            {                if (pTypes.Length > 0)                {                    //索引器                    var mb = GenerateIndexer(p.GetGetMethod());                    pb.SetGetMethod(mb);                }                else                {                    var mb = GenerateProperty(p.GetGetMethod());                    pb.SetGetMethod(mb);                }            }            if (p.CanWrite)            {                if (pTypes.Length > 0)                {                    var mb = GenerateIndexer(p.GetSetMethod());                    pb.SetSetMethod(mb);                }                else                {                    var mb = GenerateProperty(p.GetSetMethod());                    pb.SetSetMethod(mb);                }            }        }    }    private static void InitEvents()    {        var evts = GetInterfaces().SelectMany(v => v.GetEvents());        foreach (var evt in evts)        {            var eb = tb.DefineEvent(evt.Name, evt.Attributes, evt.EventHandlerType);            var add = GenerateEventEnabled(evt, evt.GetAddMethod());            eb.SetAddOnMethod(add);            var remove = GenerateEventEnabled(evt, evt.GetRemoveMethod());            eb.SetRemoveOnMethod(remove);        }    }    private static MethodBuilder GenerateMethod(MethodInfo m)    {        var pTypes = m.GetParameters().Select(v => v.ParameterType).ToArray();        var mb = tb.DefineMethod(m.Name, METHOD_ATTRIBUTES, CallingConventions.Standard, m.ReturnType, pTypes);        var ilGen = mb.GetILGenerator();        ilGen.DeclareLocal(typeof(object[])); //声明object数组变量          #region 参数准备        ilGen.Emit(OpCodes.Ldarg_0); //this        ilGen.Emit(OpCodes.Ldstr, m.Name); //string name          ilGen.Emit(OpCodes.Ldc_I4_S, pTypes.Length); //数组长度        ilGen.Emit(OpCodes.Newarr, typeof(object)); //数组        ilGen.Emit(OpCodes.Stloc_0);        for (var i = 0; i < pTypes.Length; i++)        {            ilGen.Emit(OpCodes.Ldloc_0);            ilGen.Emit(OpCodes.Ldc_I4_S, i);            ilGen.Emit(OpCodes.Ldarg_S, 1 + i);            ilGen.Emit(OpCodes.Box, pTypes[i]);            ilGen.Emit(OpCodes.Stelem_Ref);        }        #endregion        ilGen.Emit(OpCodes.Ldloc_0);        if (m.ReturnType != typeof(void))        {            var mi = typeof(TBase).GetMethod("CallReturn",                BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);            mi = mi.MakeGenericMethod(m.ReturnType);            ilGen.Emit(OpCodes.Call, mi);            var local = ilGen.DeclareLocal(m.ReturnType);            ilGen.Emit(OpCodes.Stloc_1, local);            ilGen.Emit(OpCodes.Ldloc_1, local);        }        else        {            var mi = typeof(TBase).GetMethod("CallVoid",                BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);            ilGen.Emit(OpCodes.Call, mi);        }        ilGen.Emit(OpCodes.Ret);        return mb;    }    private static MethodBuilder GenerateProperty(MethodInfo m)    {        var pTypes = m.GetParameters().Select(v => v.ParameterType).ToArray();        var mb = tb.DefineMethod(m.Name, METHOD_ATTRIBUTES, CallingConventions.Standard, m.ReturnType, pTypes);        var ilGen = mb.GetILGenerator();        #region 参数准备        ilGen.Emit(OpCodes.Ldarg_0); //this        ilGen.Emit(OpCodes.Ldstr, m.Name.Replace("set_", "").Replace("get_", "")); //string name           #endregion        if (m.Name.StartsWith("set_"))        {            ilGen.Emit(OpCodes.Ldarg_1); //value  准备参数             var mi = typeof(TBase).GetMethod("Set",                BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);            mi = mi.MakeGenericMethod(pTypes);            ilGen.Emit(OpCodes.Call, mi); //调用基类方法              //ilGen.Emit(OpCodes.Pop);        }        else        {            var mi = typeof(TBase).GetMethod("Get",                BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);            mi = mi.MakeGenericMethod(m.ReturnType);            ilGen.Emit(OpCodes.Call, mi); //调用方法            #region 返回值            var local = ilGen.DeclareLocal(m.ReturnType);            ilGen.Emit(OpCodes.Stloc_0, local);            ilGen.Emit(OpCodes.Ldloc_0, local);            #endregion        }        ilGen.Emit(OpCodes.Ret); //return        return mb;    }    private static MethodBuilder GenerateIndexer(MethodInfo m)    {        var pTypes = m.GetParameters().Select(v => v.ParameterType).ToArray();        var mb = tb.DefineMethod(m.Name, METHOD_ATTRIBUTES, CallingConventions.Standard, m.ReturnType, pTypes);        var ilGen = mb.GetILGenerator();        #region 参数准备        ilGen.DeclareLocal(typeof(object[])); //声明object数组变量          ilGen.Emit(OpCodes.Ldarg_0); //this         ilGen.Emit(OpCodes.Ldc_I4_S, pTypes.Length); //数组长度        ilGen.Emit(OpCodes.Newarr, typeof(object)); //数组        ilGen.Emit(OpCodes.Stloc_0);        var i = 0;        for (i = 0; i < pTypes.Length; i++)        {            ilGen.Emit(OpCodes.Ldloc_0);            ilGen.Emit(OpCodes.Ldc_I4_S, i);            ilGen.Emit(OpCodes.Ldarg_S, 1 + i);            ilGen.Emit(OpCodes.Box, pTypes[i]);            ilGen.Emit(OpCodes.Stelem_Ref);        }        #endregion        ilGen.Emit(OpCodes.Ldloc_0);        if (m.Name.StartsWith("set"))        {            //ilGen.Emit(OpCodes.Ldarg_S, 1 + i);//value  准备参数             var mi = typeof(TBase).GetMethod("SetItem",                BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);            ilGen.Emit(OpCodes.Call, mi); //调用基类方法              //ilGen.Emit(OpCodes.Pop);        }        else        {            var mi = typeof(TBase).GetMethod("GetItem",                BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);            mi = mi.MakeGenericMethod(m.ReturnType);            ilGen.Emit(OpCodes.Call, mi); //调用方法            #region 返回值            var local = ilGen.DeclareLocal(m.ReturnType);            ilGen.Emit(OpCodes.Stloc_1, local);            ilGen.Emit(OpCodes.Ldloc_1, local);            #endregion        }        ilGen.Emit(OpCodes.Ret); //return        return mb;    }    private static MethodBuilder GenerateEventEnabled(EventInfo evt, MethodInfo m)    {        var add = m.Name.StartsWith("add_");        var n = m.DeclaringType.Name;        var pTypes = m.GetParameters().Select(v => v.ParameterType).ToArray();        var mb = tb.DefineMethod(m.Name, METHOD_ATTRIBUTES, CallingConventions.Standard, m.ReturnType, pTypes);        var ilGen = mb.GetILGenerator();        //ilGen.DeclareLocal(typeof(EventInfo));//声明字符串变量        //ilGen.DeclareLocal(typeof(Delegate)); //value Delegate        //ilGen.Emit(OpCodes.Ldstr, evt.Name);//string evtName 字符串值        //ilGen.Emit(OpCodes.Stloc_0);//保存至变量        //ilGen.Emit(OpCodes.Ldarg_1);//Delegate dlg        //ilGen.Emit(OpCodes.Stloc_1);//保存至变量        #region 参数准备        ilGen.Emit(OpCodes.Ldarg_0);        ilGen.Emit(OpCodes.Ldstr, evt.Name);        ilGen.Emit(OpCodes.Ldarg_1);        #endregion        var mname = add ? "AddEvent" : "RemoveEvent";        ilGen.Emit(OpCodes.Call,            typeof(TBase).GetMethod(mname, BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public));        ilGen.Emit(OpCodes.Ret);        return mb;    }    private static Type[] GetInterfaces()    {        var tInterface = typeof(T);        var ts = tInterface.GetInterfaces().ToList();        ts.Add(tInterface);        return ts.ToArray();    }    private static MemberInfo[] GetMembers()    {        var members = GetInterfaces().SelectMany(v => v.GetMembers()).Distinct().ToArray();        return members;    }    public static T Create(params object[] args)    {        return (T)Activator.CreateInstance(Type, args);    }    public static Type GetGenerateType()    {        return Type;    }}
 |