using System; using System.Collections.Generic; using System.Linq; using System.Reflection; using System.Reflection.Emit; using System.Text; using System.Threading.Tasks; namespace WCS.Core { /// /// 动态创建接口实例 /// /// 接口 /// 基类 public static class Generator where TBase : IProtocolProxy { static TypeBuilder tb; static Type Type; static Generator() { if (!typeof(T).IsInterface) throw new Exception("T必须是interface"); if (!typeof(TBase).IsClass) throw new Exception("TBase必须是class"); AssemblyName myAssemblyName = new AssemblyName(); myAssemblyName.Name = typeof(T).Name + "_Generate"; AssemblyBuilder myAssembly = AssemblyBuilder.DefineDynamicAssembly(myAssemblyName, AssemblyBuilderAccess.RunAndCollect); //AssemblyBuilder myAssembly = AssemblyBuilder.DefineDynamicAssembly(myAssemblyName, AssemblyBuilderAccess.RunAndSave); ModuleBuilder myModule = myAssembly.DefineDynamicModule("Main"); tb = myModule.DefineType(typeof(T).Name + "_Generate", TypeAttributes.Public, typeof(TBase), new Type[] { typeof(T) }); InitConstructors(); InitMethods(); InitProperties(); InitEvents(); try { Type = tb.CreateTypeInfo().AsType();//.CreateType(); } catch (Exception ex) { } //myAssembly.Save(typeof(T).Name + ".dll"); } private const MethodAttributes METHOD_ATTRIBUTES = MethodAttributes.Public | MethodAttributes.NewSlot | MethodAttributes.Virtual | MethodAttributes.Final | MethodAttributes.HideBySig; 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 (int i = 0; i < pTypes.Length; i++) { build.DefineParameter(i + 1, ParameterAttributes.In, "p" + i); } var il = build.GetILGenerator(); il.Emit(OpCodes.Ldarg_0); for (int 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); } } 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); } } static void InitProperties() { var ps = GetInterfaces().SelectMany(v => v.GetProperties()); ps = GetMembers().OfType(); 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); } } } } 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); } } 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 (int 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); LocalBuilder 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; } 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 返回值 LocalBuilder 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; } 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); int 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 返回值 LocalBuilder 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; } static MethodBuilder GenerateEventEnabled(EventInfo evt, MethodInfo m) { bool 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; } static Type[] GetInterfaces() { var tInterface = typeof(T); var ts = tInterface.GetInterfaces().ToList(); ts.Add(tInterface); return ts.ToArray(); } 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; } } }