// The caller sends in an AppDomain type. public static void CreateMyAsm(AppDomain curAppDomain) { // Establish general assembly characteristics. AssemblyName assemblyName = new AssemblyName(); assemblyName.Name = "MyAssembly"; assemblyName.Version = new Version("1.0.0.0"); // Create new assembly within the current AppDomain. // AssemblyBuilder assembly = AppDomain.CurrentDomain.DefineDynamicAssembly(assemblyName, AssemblyBuilder assembly = curAppDomain.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Save); // Given that we are building a single-file // assembly, the name of the module is the same as the assembly. ModuleBuilder module = assembly.DefineDynamicModule("MyAssembly", "MyAssembly.dll"); // Define a public class named "HelloWorld". TypeBuilder helloWorldClass = module.DefineType("MyAssembly.HelloWorld", TypeAttributes.Public); // Define a private String member variable named "theMessage". FieldBuilder msgField = helloWorldClass.DefineField("theMessage", Type.GetType("System.String"), FieldAttributes.Private); // Create the custom ctor. Type[] constructorArgs = new Type[1]; constructorArgs[0] = typeof(string); ConstructorBuilder constructor = helloWorldClass.DefineConstructor(MethodAttributes.Public, CallingConventions.Standard, constructorArgs); ILGenerator constructorIL = constructor.GetILGenerator(); constructorIL.Emit(OpCodes.Ldarg_0); Type objectClass = typeof(object); ConstructorInfo superConstructor = objectClass.GetConstructor(new Type[0]); constructorIL.Emit(OpCodes.Call, superConstructor); constructorIL.Emit(OpCodes.Ldarg_0); constructorIL.Emit(OpCodes.Ldarg_1); constructorIL.Emit(OpCodes.Stfld, msgField); constructorIL.Emit(OpCodes.Ret); // Create the default ctor. helloWorldClass.DefineDefaultConstructor(MethodAttributes.Public); // Now create the GetMsg() method. MethodBuilder getMsgMethod = helloWorldClass.DefineMethod("GetMsg", MethodAttributes.Public, typeof(string), null); ILGenerator methodIL = getMsgMethod.GetILGenerator(); methodIL.Emit(OpCodes.Ldarg_0); methodIL.Emit(OpCodes.Ldfld, msgField); methodIL.Emit(OpCodes.Ret); // Create the SayHello method. MethodBuilder sayHiMethod = helloWorldClass.DefineMethod("SayHello", MethodAttributes.Public, null, null); methodIL = sayHiMethod.GetILGenerator(); methodIL.EmitWriteLine("Hello from the HelloWorld class!"); methodIL.Emit(OpCodes.Ret); // "Bake" the class HelloWorld. // (Baking is the formal term for emitting the type.) helloWorldClass.CreateType(); // (Optionally) save the assembly to file. assembly.Save("MyAssembly.dll"); }
public Type EmitProxyType(string entityTypeName, IDictionary <string, Type> entityFieldDic) { string typeName = string.Format("{0}.{1}", this.assemblyName, entityTypeName); TypeBuilder typeBuilder = this.moduleBuilder.DefineType(typeName, TypeAttributes.Public | TypeAttributes.Class | TypeAttributes.Serializable); //typeBuilder.AddInterfaceImplementation(interfaceType); List <FieldBuilder> fieldBuilderList = new List <FieldBuilder>(); foreach (string propertyName in entityFieldDic.Keys) { #region 定义属性 Type propertyType = entityFieldDic[propertyName]; FieldBuilder fieldBuilder = typeBuilder.DefineField("m_" + propertyName, propertyType, FieldAttributes.Private); fieldBuilderList.Add(fieldBuilder); fieldBuilder.SetConstant(TypeHelper.ChangeType(propertyType, TypeHelper.GetDefaultValue(propertyType))); PropertyBuilder propertyBuilder = typeBuilder.DefineProperty(propertyName, PropertyAttributes.None, propertyType, null); //定义属性的get方法 MethodBuilder getPropertyBuilder = typeBuilder.DefineMethod("get", MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.HideBySig, propertyType, Type.EmptyTypes); ILGenerator getAIL = getPropertyBuilder.GetILGenerator(); getAIL.Emit(OpCodes.Ldarg_0); getAIL.Emit(OpCodes.Ldfld, fieldBuilder); getAIL.Emit(OpCodes.Ret); //定义属性A的set方法 MethodBuilder setPropertyABuilder = typeBuilder.DefineMethod("set", MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.HideBySig, null, new Type[] { propertyType }); ILGenerator setAIL = setPropertyABuilder.GetILGenerator(); setAIL.Emit(OpCodes.Ldarg_0); setAIL.Emit(OpCodes.Ldarg_1); setAIL.Emit(OpCodes.Stfld, fieldBuilder); setAIL.Emit(OpCodes.Ret); propertyBuilder.SetGetMethod(getPropertyBuilder); propertyBuilder.SetSetMethod(setPropertyABuilder); #endregion } #region Emit Ctor ConstructorBuilder ctor = typeBuilder.DefineConstructor(MethodAttributes.Public, CallingConventions.Standard, Type.EmptyTypes); ILGenerator ctorGen = ctor.GetILGenerator(); ctorGen.Emit(OpCodes.Ldarg_0); ctorGen.Emit(OpCodes.Call, typeof(object).GetConstructor(new Type[] { })); foreach (FieldBuilder fieldBuilder in fieldBuilderList) { if (fieldBuilder.FieldType == typeof(string)) { ctorGen.Emit(OpCodes.Ldarg_0); ctorGen.Emit(OpCodes.Ldstr, ""); ctorGen.Emit(OpCodes.Stfld, fieldBuilder); } } ctorGen.Emit(OpCodes.Ret); #endregion Type target = typeBuilder.CreateType(); return(target); }
static void DefineCtors(TypeBuilder proxyTB, Type superClass, string initName, string postInitName, ISeq ctors, ISeq ctorTypes, FieldBuilder initFB, FieldBuilder postInitFB, FieldBuilder stateFB, string factoryName) { ISeq s1 = ctors; for (ISeq s = ctorTypes; s != null; s = s.next()) { // TODO: Get rid of this mess by making sure the metadata on the keys of the constructors map gets copied to the constructor-types map. Sigh. IPersistentMap ctorAttributes = GenInterface.ExtractAttributes(RT.meta(((IMapEntry)s1.first()).key())); s1 = s1.next(); IMapEntry me = (IMapEntry)s.first(); ISeq thisParamTypesV = (ISeq)me.key(); ISeq baseParamTypesV = (ISeq)me.val(); Type[] thisParamTypes = CreateTypeArray(thisParamTypesV); Type[] baseParamTypes = CreateTypeArray(baseParamTypesV); BindingFlags flags = BindingFlags.CreateInstance | BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance; ConstructorInfo superCtor = superClass.GetConstructor(flags, null, baseParamTypes, null); if (superCtor == null || superCtor.IsPrivate) { throw new InvalidOperationException("Base class constructor missing or private"); } ConstructorBuilder cb = proxyTB.DefineConstructor(MethodAttributes.Public, CallingConventions.HasThis, thisParamTypes); GenInterface.SetCustomAttributes(cb, ctorAttributes); CljILGen gen = new CljILGen(cb.GetILGenerator()); Label noInitLabel = gen.DefineLabel(); Label noPostInitLabel = gen.DefineLabel(); Label endPostInitLabel = gen.DefineLabel(); Label endLabel = gen.DefineLabel(); LocalBuilder locSuperArgs = gen.DeclareLocal(typeof(object)); LocalBuilder locInitVal = gen.DeclareLocal(typeof(object)); if (initFB != null) { // init supplied EmitGetVar(gen, initFB); gen.Emit(OpCodes.Dup); gen.Emit(OpCodes.Brfalse_S, noInitLabel); gen.Emit(OpCodes.Castclass, typeof(IFn)); // box init args for (int i = 0; i < thisParamTypes.Length; i++) { gen.EmitLoadArg(i + 1); // gen.Emit(OpCodes.Ldarg, i + 1); if (thisParamTypes[i].IsValueType) { gen.Emit(OpCodes.Box, thisParamTypes[i]); } } gen.EmitCall(Compiler.Methods_IFn_invoke[thisParamTypes.Length]); // gen.Emit(OpCodes.Call, Compiler.Methods_IFn_invoke[thisParamTypes.Length]); // Expecting: [[super-ctor-args...] state] // store the init return in a local gen.Emit(OpCodes.Dup); gen.Emit(OpCodes.Stloc, locInitVal); // store the first element in a local gen.EmitInt(0); // gen.Emit(OpCodes.Ldc_I4_0); gen.EmitCall(Method_RT_nth); // gen.Emit(OpCodes.Call, Method_RT_nth); gen.Emit(OpCodes.Stloc, locSuperArgs); // Stack this + super-ctor-args + call base-class ctor. gen.EmitLoadArg(0); // gen.Emit(OpCodes.Ldarg_0); for (int i = 0; i < baseParamTypes.Length; i++) { gen.Emit(OpCodes.Ldloc, locSuperArgs); gen.EmitInt(i); // gen.Emit(OpCodes.Ldc_I4, i); gen.EmitCall(Method_RT_nth); // gen.Emit(OpCodes.Call, Method_RT_nth); if (baseParamTypes[i].IsValueType) { gen.Emit(OpCodes.Unbox_Any, baseParamTypes[i]); } else { gen.Emit(OpCodes.Castclass, baseParamTypes[i]); } } gen.Emit(OpCodes.Call, superCtor); if (stateFB != null) { gen.EmitLoadArg(0); // gen.Emit(OpCodes.Ldarg_0); gen.Emit(OpCodes.Ldloc, locInitVal); gen.EmitInt(1); // gen.Emit(OpCodes.Ldc_I4_1); gen.EmitCall(Method_RT_nth); // gen.Emit(OpCodes.Call, Method_RT_nth); gen.Emit(OpCodes.Castclass, typeof(object)); gen.EmitFieldSet(stateFB); // gen.Emit(OpCodes.Stfld, stateFB); } gen.Emit(OpCodes.Br_S, endLabel); // No init found gen.MarkLabel(noInitLabel); gen.Emit(OpCodes.Pop); EmitUnsupported(gen, initName); gen.MarkLabel(endLabel); } else // no InitFB supplied. { bool ok = thisParamTypes.Length == baseParamTypes.Length; for (int i = 0; ok && i < thisParamTypes.Length; i++) { ok = baseParamTypes[i].IsAssignableFrom(thisParamTypes[i]); } if (!ok) { throw new InvalidOperationException(":init not specified, but ctor and super ctor args differ"); } gen.EmitLoadArg(0); // gen.Emit(OpCodes.Ldarg_0); for (int i = 0; i < thisParamTypes.Length; i++) { gen.EmitLoadArg(i + 1); // gen.Emit(OpCodes.Ldarg, i + 1); if (baseParamTypes[i] != thisParamTypes[i]) { gen.Emit(OpCodes.Castclass, baseParamTypes[i]); } } gen.Emit(OpCodes.Call, superCtor); } if (postInitFB != null) { // post-init supplied EmitGetVar(gen, postInitFB); gen.Emit(OpCodes.Dup); gen.Emit(OpCodes.Brfalse_S, noPostInitLabel); gen.Emit(OpCodes.Castclass, typeof(IFn)); // box init args gen.EmitLoadArg(0); // gen.Emit(OpCodes.Ldarg_0); for (int i = 0; i < thisParamTypes.Length; i++) { gen.EmitLoadArg(i + 1); // gen.Emit(OpCodes.Ldarg, i + 1); if (thisParamTypes[i].IsValueType) { gen.Emit(OpCodes.Box, thisParamTypes[i]); } gen.Emit(OpCodes.Castclass, thisParamTypes[i]); } gen.EmitCall(Compiler.Methods_IFn_invoke[thisParamTypes.Length + 1]); // gen.Emit(OpCodes.Call, Compiler.Methods_IFn_invoke[thisParamTypes.Length + 1]); gen.Emit(OpCodes.Pop); gen.Emit(OpCodes.Br_S, endPostInitLabel); // no post-init found gen.MarkLabel(noPostInitLabel); gen.Emit(OpCodes.Pop); EmitUnsupported(gen, postInitName + " not defined"); gen.MarkLabel(endPostInitLabel); } gen.Emit(OpCodes.Ret); if (!String.IsNullOrEmpty(factoryName)) { MethodBuilder factoryMB = proxyTB.DefineMethod(factoryName, MethodAttributes.Public | MethodAttributes.Static, CallingConventions.Standard, proxyTB, thisParamTypes); CljILGen genf = new CljILGen(factoryMB.GetILGenerator()); LocalBuilder[] locals = new LocalBuilder[thisParamTypes.Length]; for (int i = 0; i < thisParamTypes.Length; i++) { locals[i] = genf.DeclareLocal(thisParamTypes[i]); genf.EmitLoadArg(i); // genf.Emit(OpCodes.Ldarg, i); genf.Emit(OpCodes.Stloc, locals[i]); } for (int i = 0; i < thisParamTypes.Length; i++) { genf.EmitLoadArg(i); // genf.Emit(OpCodes.Ldarg, i); } genf.EmitNew(cb); // genf.Emit(OpCodes.Newobj, cb); genf.Emit(OpCodes.Ret); } } }
internal static IEnumerable ToDataSource(this IEnumerable <Graphic> graphics, Dictionary <string, Type> fieldInfo, Dictionary <string, object[]> rangeDomainInfo, Dictionary <string, Field> fieldProps, string uniqueID, IEnumerable <Graphic> filterGraphics, out Type objectType) { objectType = null; IDictionary firstDict = null; IEnumerable <IDictionary <string, object> > list = GetGraphicsEnumerable(graphics); if (fieldInfo == null) { if (list != null) { IEnumerator enumList = list.GetEnumerator(); if (enumList != null && enumList.MoveNext()) { firstDict = enumList.Current as IDictionary; if (firstDict != null) { while (enumList.MoveNext()) { IDictionary nextDict = enumList.Current as IDictionary; foreach (DictionaryEntry pair in nextDict) { Type t = GetValueType(pair.Key as string, pair.Value, fieldInfo); if (!firstDict.Contains(pair.Key)) // Attribute doesn't exist => add it { object defaultValue = t.IsValueType ? Activator.CreateInstance(t) : null; firstDict.Add(pair.Key, defaultValue); } else // Attribute exists => check for data type compatibility { Type typeInFirstDict = GetValueType(pair.Key as string, firstDict[pair.Key], fieldInfo); if (typeInFirstDict != typeof(object) && // object type in firstDict covers all data types pair.Value != null && // null values in nextDict match the nullable data type associated with the attribute in firstDict !t.IsOfType(typeInFirstDict)) // attribute data types don't match { throw new InvalidCastException(string.Format(Properties.Resources.FeatureDataGrid_MixedAttributeTypesNotAllowed, firstDict[pair.Key].GetType(), pair.Key)); } } } } } } } } if (firstDict == null && fieldInfo == null) { return new object[] { } } ; string typeSignature = GetTypeSignature(firstDict, fieldInfo); Dictionary <string, Type> properties = new Dictionary <string, Type>(); _fieldMapping = new Dictionary <string, string>(); if (fieldInfo != null) // FeatureLayer { foreach (string key in fieldInfo.Keys) { string keyToUse = GetMappedKey(key); Type t = fieldInfo[key]; properties.Add(keyToUse, t); } } else // GraphicsLayer { foreach (DictionaryEntry pair in firstDict) { string keyToUse = GetMappedKey(pair.Key.ToString()); Type t = GetValueType(keyToUse, pair.Value, fieldInfo); properties.Add(keyToUse, t); } } objectType = GetTypeByTypeSignature(typeSignature); if (objectType == null) { TypeBuilder tb = GetTypeBuilder(typeSignature); FieldBuilder fieldBuilder = tb.DefineField("_graphicSibling", typeof(Graphic), FieldAttributes.Private); ConstructorBuilder constructorBuilder = tb.DefineConstructor(MethodAttributes.Public, CallingConventions.Standard, new Type[] { typeof(Graphic) }); ILGenerator cbIL = constructorBuilder.GetILGenerator(); cbIL.Emit(OpCodes.Ldarg_0); cbIL.Emit(OpCodes.Call, typeof(object).GetConstructor(Type.EmptyTypes)); cbIL.Emit(OpCodes.Ldarg_0); cbIL.Emit(OpCodes.Ldarg_1); cbIL.Emit(OpCodes.Stfld, fieldBuilder); cbIL.Emit(OpCodes.Ret); MethodBuilder methodBuilder = tb.DefineMethod("GetGraphicSibling", MethodAttributes.Public, typeof(Graphic), Type.EmptyTypes); ILGenerator mbIL = methodBuilder.GetILGenerator(); mbIL.Emit(OpCodes.Ldarg_0); mbIL.Emit(OpCodes.Ldfld, fieldBuilder); mbIL.Emit(OpCodes.Ret); int order = 0; foreach (string key in properties.Keys) { if (fieldProps != null) // FeatureLayer { if (_fieldMapping.KeyOfValue(key) != null) { string mappedKey = _fieldMapping.KeyOfValue(key); if (fieldProps.ContainsKey(mappedKey)) // Only create the property if the key is contained in field properties { Field fld = fieldProps[mappedKey]; if (IsViewableAttribute(fld)) { CreateProperty(tb, key, properties[key], rangeDomainInfo, fld, order++, uniqueID == key); } } } } else // GraphicsLayer { CreateProperty(tb, key, properties[key], rangeDomainInfo, null, order++, uniqueID == key); } } objectType = tb.CreateType(); _typeBySignature.Add(typeSignature, objectType); } return(GenerateEnumerable(objectType, graphics, properties.Keys.ToArray(), filterGraphics)); }
/// <summary> /// 动态生成接口的实现类 /// </summary> /// <param name="interfaceType"></param> /// <param name="constructor"></param> /// <returns></returns> private Type BuildTargetType(Type interfaceType, params object[] constructor) { targetType = interfaceType; string assemblyName = targetType.Name + "ProxyAssembly"; string moduleName = targetType.Name + "ProxyModule"; string typeName = targetType.Name + "Proxy"; AssemblyName assyName = new AssemblyName(assemblyName); AssemblyBuilder assyBuilder = AssemblyBuilder.DefineDynamicAssembly(assyName, AssemblyBuilderAccess.Run); ModuleBuilder modBuilder = assyBuilder.DefineDynamicModule(moduleName); //新类型的属性 TypeAttributes newTypeAttribute = TypeAttributes.Class | TypeAttributes.Public; //父类型 Type parentType; //要实现的接口 Type[] interfaceTypes; if (targetType.IsInterface) { parentType = typeof(object); interfaceTypes = new Type[] { targetType }; } else { parentType = targetType; interfaceTypes = Type.EmptyTypes; } //得到类型生成器 TypeBuilder typeBuilder = modBuilder.DefineType(typeName, newTypeAttribute, parentType, interfaceTypes); //定义一个字段存放httpService var httpType = typeof(HttpService); FieldBuilder httpServiceField = typeBuilder.DefineField("httpService", httpType, FieldAttributes.Public); //定义一个字段存放IServiceProvider var iServiceProviderType = typeof(IServiceProvider); FieldBuilder serviceProviderField = typeBuilder.DefineField("iServiceProvider", iServiceProviderType, FieldAttributes.Public); //定义一个集合存放参数集合 FieldBuilder paramterArrField = typeBuilder.DefineField("paramterArr", typeof(List <object>), FieldAttributes.Public); //创建构造函数 ConstructorBuilder constructorBuilder = typeBuilder.DefineConstructor(MethodAttributes.Public, CallingConventions.Standard, new Type[] { httpType, iServiceProviderType }); //il创建构造函数,对httpService和IServiceProvider两个字段进行赋值,同时初始化存放参数的集合 ILGenerator ilgCtor = constructorBuilder.GetILGenerator(); ilgCtor.Emit(OpCodes.Ldarg_0); //加载当前类 ilgCtor.Emit(OpCodes.Ldarg_1); ilgCtor.Emit(OpCodes.Stfld, httpServiceField); ilgCtor.Emit(OpCodes.Ldarg_0); //加载当前类 ilgCtor.Emit(OpCodes.Ldarg_2); ilgCtor.Emit(OpCodes.Stfld, serviceProviderField); ilgCtor.Emit(OpCodes.Ldarg_0); //加载当前类 ilgCtor.Emit(OpCodes.Newobj, typeof(List <object>).GetConstructors().First()); ilgCtor.Emit(OpCodes.Stfld, paramterArrField); ilgCtor.Emit(OpCodes.Ret); //返回 MethodInfo[] targetMethods = targetType.GetMethods(); foreach (MethodInfo targetMethod in targetMethods) { //只挑出virtual的方法 if (targetMethod.IsVirtual) { //缓存接口的方法体,便于后续将方法体传递给httpService string methodKey = Guid.NewGuid().ToString(); MethodsCache[methodKey] = targetMethod; //得到方法的各个参数的类型和参数 var paramInfo = targetMethod.GetParameters(); var parameterType = paramInfo.Select(it => it.ParameterType).ToArray(); var returnType = targetMethod.ReturnType; //方法返回值只能是task,即只支持异步,因为http操作是io操作 if (!typeof(Task).IsAssignableFrom(returnType)) { throw new Exception("return type must be task<>"); } var underType = returnType.IsGenericType ? returnType.GetGenericArguments().First() : returnType; //通过emit生成方法体 MethodBuilder methodBuilder = typeBuilder.DefineMethod(targetMethod.Name, MethodAttributes.Public | MethodAttributes.Virtual, targetMethod.ReturnType, parameterType); ILGenerator ilGen = methodBuilder.GetILGenerator(); MethodInfo executeMethod = null; var methodTmp = httpType.GetMethod("ExecuteAsync"); if (methodTmp == null) { throw new Exception("找不到执行方法"); } executeMethod = methodTmp.IsGenericMethod ? methodTmp.MakeGenericMethod(underType) : methodTmp; // 栈底放这玩意,加载字段前要加载类实例,即Ldarg_0 ilGen.Emit(OpCodes.Ldarg_0); ilGen.Emit(OpCodes.Ldfld, httpServiceField); //把所有参数都放到list<object>里 ilGen.Emit(OpCodes.Ldarg_0); ilGen.Emit(OpCodes.Ldfld, paramterArrField); for (int i = 0; i < parameterType.Length; i++) { ilGen.Emit(OpCodes.Dup); ilGen.Emit(OpCodes.Ldarg_S, i + 1); if (parameterType[i].IsValueType) { ilGen.Emit(OpCodes.Box, parameterType[i]); } ilGen.Emit(OpCodes.Callvirt, typeof(List <object>).GetMethod("Add")); } // 当前栈[httpServiceField paramterArrField] //从缓存里取出方法体 ilGen.Emit(OpCodes.Call, typeof(FeignProxyBuilder).GetMethod("get_MethodsCache", BindingFlags.Static | BindingFlags.Public)); ilGen.Emit(OpCodes.Ldstr, methodKey); ilGen.Emit(OpCodes.Call, typeof(Dictionary <string, MethodInfo>).GetMethod("get_Item")); ilGen.Emit(OpCodes.Ldarg_0); ilGen.Emit(OpCodes.Ldfld, serviceProviderField); ilGen.Emit(OpCodes.Callvirt, executeMethod); //清空list里的参数 ilGen.Emit(OpCodes.Ldarg_0); ilGen.Emit(OpCodes.Ldfld, paramterArrField); ilGen.Emit(OpCodes.Callvirt, typeof(List <object>).GetMethod("Clear")); // pop the stack if return void if (targetMethod.ReturnType == typeof(void)) { ilGen.Emit(OpCodes.Pop); } // complete ilGen.Emit(OpCodes.Ret); typeBuilder.DefineMethodOverride(methodBuilder, targetMethod); } } var resultType = typeBuilder.CreateTypeInfo().AsType(); return(resultType); }
private static bool TryCreatePropertyDescriptor(ref PropertyDescriptor descriptor) { try { PropertyInfo property = descriptor.ComponentType.GetProperty(descriptor.Name); if (property == null) { return(false); } lock (properties) { PropertyDescriptor foundBuiltAlready; if (properties.TryGetValue(property, out foundBuiltAlready)) { descriptor = foundBuiltAlready; return(true); } string name = "_c" + Interlocked.Increment(ref counter).ToString(); TypeBuilder tb = moduleBuilder.DefineType(name, TypeAttributes.Sealed | TypeAttributes.NotPublic | TypeAttributes.Class | TypeAttributes.BeforeFieldInit | TypeAttributes.AutoClass | TypeAttributes.Public, typeof(ChainingPropertyDescriptor)); // ctor calls base ConstructorBuilder cb = tb.DefineConstructor( MethodAttributes.HideBySig | MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName, CallingConventions.Standard, new Type[] { typeof(PropertyDescriptor) }); ILGenerator il = cb.GetILGenerator(); il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldarg_1); il.Emit(OpCodes.Call, typeof(ChainingPropertyDescriptor).GetConstructor( BindingFlags.NonPublic | BindingFlags.Instance, null, new Type[] { typeof(PropertyDescriptor) }, null)); il.Emit(OpCodes.Ret); MethodBuilder mb; MethodInfo baseMethod; if (property.CanRead) { // obtain the implementation that we want to override baseMethod = typeof(ChainingPropertyDescriptor).GetMethod("GetValue"); // create a new method that accepts an object and returns an object (as per the base) mb = tb.DefineMethod(baseMethod.Name, MethodAttributes.HideBySig | MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.Final, baseMethod.CallingConvention, baseMethod.ReturnType, new Type[] { typeof(object) }); // start writing IL into the method il = mb.GetILGenerator(); if (property.DeclaringType.IsValueType) { // upbox the object argument into our known (instance) struct type LocalBuilder lb = il.DeclareLocal(property.DeclaringType); il.Emit(OpCodes.Ldarg_1); il.Emit(OpCodes.Unbox_Any, property.DeclaringType); il.Emit(OpCodes.Stloc_0); il.Emit(OpCodes.Ldloca_S, lb); } else { // cast the object argument into our known class type il.Emit(OpCodes.Ldarg_1); il.Emit(OpCodes.Castclass, property.DeclaringType); } // call the "get" method il.Emit(OpCodes.Callvirt, property.GetGetMethod()); if (property.PropertyType.IsValueType) { // box it from the known (value) struct type il.Emit(OpCodes.Box, property.PropertyType); } // return the value il.Emit(OpCodes.Ret); // signal that this method should override the base tb.DefineMethodOverride(mb, baseMethod); } bool supportsChangeEvents = descriptor.SupportsChangeEvents, isReadOnly = descriptor.IsReadOnly; // override SupportsChangeEvents baseMethod = typeof(ChainingPropertyDescriptor).GetProperty("SupportsChangeEvents").GetGetMethod(); mb = tb.DefineMethod(baseMethod.Name, MethodAttributes.HideBySig | MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.Final | MethodAttributes.SpecialName, baseMethod.CallingConvention, baseMethod.ReturnType, Type.EmptyTypes); il = mb.GetILGenerator(); if (supportsChangeEvents) { il.Emit(OpCodes.Ldc_I4_1); } else { il.Emit(OpCodes.Ldc_I4_0); } il.Emit(OpCodes.Ret); tb.DefineMethodOverride(mb, baseMethod); // override IsReadOnly baseMethod = typeof(ChainingPropertyDescriptor).GetProperty("IsReadOnly").GetGetMethod(); mb = tb.DefineMethod(baseMethod.Name, MethodAttributes.HideBySig | MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.Final | MethodAttributes.SpecialName, baseMethod.CallingConvention, baseMethod.ReturnType, Type.EmptyTypes); il = mb.GetILGenerator(); if (isReadOnly) { il.Emit(OpCodes.Ldc_I4_1); } else { il.Emit(OpCodes.Ldc_I4_0); } il.Emit(OpCodes.Ret); tb.DefineMethodOverride(mb, baseMethod); // for classes, implement write (would be lost in unbox for structs) if (!property.DeclaringType.IsValueType) { if (!isReadOnly && property.CanWrite) { // override set method baseMethod = typeof(ChainingPropertyDescriptor).GetMethod("SetValue"); mb = tb.DefineMethod(baseMethod.Name, MethodAttributes.HideBySig | MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.Final, baseMethod.CallingConvention, baseMethod.ReturnType, new Type[] { typeof(object), typeof(object) }); il = mb.GetILGenerator(); il.Emit(OpCodes.Ldarg_1); il.Emit(OpCodes.Castclass, property.DeclaringType); il.Emit(OpCodes.Ldarg_2); if (property.PropertyType.IsValueType) { il.Emit(OpCodes.Unbox_Any, property.PropertyType); } else { il.Emit(OpCodes.Castclass, property.PropertyType); } il.Emit(OpCodes.Callvirt, property.GetSetMethod()); il.Emit(OpCodes.Ret); tb.DefineMethodOverride(mb, baseMethod); } if (supportsChangeEvents) { EventInfo ei = property.DeclaringType.GetEvent(property.Name + "Changed"); if (ei != null) { baseMethod = typeof(ChainingPropertyDescriptor).GetMethod("AddValueChanged"); mb = tb.DefineMethod(baseMethod.Name, MethodAttributes.HideBySig | MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.Final | MethodAttributes.SpecialName, baseMethod.CallingConvention, baseMethod.ReturnType, new Type[] { typeof(object), typeof(EventHandler) }); il = mb.GetILGenerator(); il.Emit(OpCodes.Ldarg_1); il.Emit(OpCodes.Castclass, property.DeclaringType); il.Emit(OpCodes.Ldarg_2); il.Emit(OpCodes.Callvirt, ei.GetAddMethod()); il.Emit(OpCodes.Ret); tb.DefineMethodOverride(mb, baseMethod); baseMethod = typeof(ChainingPropertyDescriptor).GetMethod("RemoveValueChanged"); mb = tb.DefineMethod(baseMethod.Name, MethodAttributes.HideBySig | MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.Final | MethodAttributes.SpecialName, baseMethod.CallingConvention, baseMethod.ReturnType, new Type[] { typeof(object), typeof(EventHandler) }); il = mb.GetILGenerator(); il.Emit(OpCodes.Ldarg_1); il.Emit(OpCodes.Castclass, property.DeclaringType); il.Emit(OpCodes.Ldarg_2); il.Emit(OpCodes.Callvirt, ei.GetRemoveMethod()); il.Emit(OpCodes.Ret); tb.DefineMethodOverride(mb, baseMethod); } } } PropertyDescriptor newDesc = tb.CreateType() .GetConstructor(new Type[] { typeof(PropertyDescriptor) }) .Invoke(new object[] { descriptor }) as PropertyDescriptor; if (newDesc == null) { return(false); } descriptor = newDesc; properties.Add(property, descriptor); return(true); } } catch { return(false); } }
public CodeGen DefineConstructor(Type[] paramTypes) { ConstructorBuilder cb = _myType.DefineConstructor(MethodAttributes.Public, CallingConventions.Standard, paramTypes); return(CreateCodeGen(cb, cb.GetILGenerator(), paramTypes)); }
public static IComparer Compile(AssemblyEmitter assembly, Type objectType, OrderInfo[] orders) { TypeBuilder typeBuilder = assembly.DefineType( "__sort", TypeAttributes.Public, typeof(object) ); #region Constructor { ConstructorBuilder ctor = typeBuilder.DefineConstructor( MethodAttributes.Public, CallingConventions.Standard, Type.EmptyTypes ); ILGenerator il = ctor.GetILGenerator(); // : base() il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Call, typeof(object).GetConstructor(Type.EmptyTypes)); // return; il.Emit(OpCodes.Ret); } #endregion #region IComparer typeBuilder.AddInterfaceImplementation(typeof(IComparer)); MethodBuilder compareMethod; #region Compare { MethodEmitter emitter = new MethodEmitter(typeBuilder); emitter.Define( /* name */ "Compare", /* attr */ MethodAttributes.Public | MethodAttributes.Virtual, /* return */ typeof(int), /* params */ new Type[] { typeof(object), typeof(object) }); LocalBuilder a = emitter.CreateLocal(objectType); LocalBuilder b = emitter.CreateLocal(objectType); LocalBuilder v = emitter.CreateLocal(typeof(int)); emitter.LoadArgument(1); emitter.CastAs(objectType); emitter.StoreLocal(a); emitter.LoadArgument(2); emitter.CastAs(objectType); emitter.StoreLocal(b); emitter.Load(0); emitter.StoreLocal(v); Label end = emitter.CreateLabel(); for (int i = 0; i < orders.Length; ++i) { if (i > 0) { emitter.LoadLocal(v); emitter.BranchIfTrue(end); // if ( v != 0 ) return v; } OrderInfo orderInfo = orders[i]; Property prop = orderInfo.Property; int sign = orderInfo.Sign; emitter.LoadLocal(a); emitter.Chain(prop); bool couldCompare = emitter.CompareTo(sign, delegate() { emitter.LoadLocal(b); emitter.Chain(prop); }); if (!couldCompare) { throw new InvalidOperationException("Property is not comparable."); } emitter.StoreLocal(v); } emitter.MarkLabel(end); emitter.LoadLocal(v); emitter.Return(); typeBuilder.DefineMethodOverride( emitter.Method, typeof(IComparer).GetMethod( "Compare", new Type[] { typeof(object), typeof(object) } ) ); compareMethod = emitter.Method; } #endregion #endregion Type comparerType = typeBuilder.CreateType(); return((IComparer)Activator.CreateInstance(comparerType)); }
/// <summary> /// The CreateType method creates a new data class with a given set of public properties and returns the System.Type object for the newly created class. If a data class with an identical sequence of properties has already been created, the System.Type object for this class is returned. /// Data classes implement private instance variables and read/write property accessors for the specified properties.Data classes also override the Equals and GetHashCode members to implement by-value equality. /// Data classes are created in an in-memory assembly in the current application domain. All data classes inherit from <see cref="DynamicClass"/> and are given automatically generated names that should be considered private (the names will be unique within the application domain but not across multiple invocations of the application). Note that once created, a data class stays in memory for the lifetime of the current application domain. There is currently no way to unload a dynamically created data class. /// The dynamic expression parser uses the CreateClass methods to generate classes from data object initializers. This feature in turn is often used with the dynamic Select method to create projections. /// </summary> /// <param name="properties">The DynamicProperties</param> /// <param name="createParameterCtor">Create a constructor with parameters. Default set to true. Note that for Linq-to-Database objects, this needs to be set to false.</param> /// <returns>Type</returns> /// <example> /// <code> /// <![CDATA[ /// DynamicProperty[] props = new DynamicProperty[] { new DynamicProperty("Name", typeof(string)), new DynamicProperty("Birthday", typeof(DateTime)) }; /// Type type = DynamicClassFactory.CreateType(props); /// DynamicClass dynamicClass = Activator.CreateInstance(type) as DynamicClass; /// dynamicClass.SetDynamicProperty("Name", "Albert"); /// dynamicClass.SetDynamicProperty("Birthday", new DateTime(1879, 3, 14)); /// Console.WriteLine(dynamicClass); /// ]]> /// </code> /// </example> public static Type CreateType([NotNull] IList <DynamicProperty> properties, bool createParameterCtor = true) { Check.HasNoNulls(properties, nameof(properties)); Type[] types = properties.Select(p => p.Type).ToArray(); string[] names = properties.Select(p => p.Name).ToArray(); string key = GenerateKey(properties, createParameterCtor); Type type; if (!GeneratedTypes.TryGetValue(key, out type)) { // We create only a single class at a time, through this lock // Note that this is a variant of the double-checked locking. // It is safe because we are using a thread safe class. lock (GeneratedTypes) { if (!GeneratedTypes.TryGetValue(key, out type)) { int index = Interlocked.Increment(ref _index); string name = names.Length != 0 ? $"<>f__AnonymousType{index}`{names.Length}" : $"<>f__AnonymousType{index}"; TypeBuilder tb = ModuleBuilder.DefineType(name, TypeAttributes.AnsiClass | TypeAttributes.Public | TypeAttributes.Class | TypeAttributes.AutoLayout | TypeAttributes.BeforeFieldInit, typeof(DynamicClass)); tb.SetCustomAttribute(CompilerGeneratedAttributeBuilder); GenericTypeParameterBuilder[] generics; if (names.Length != 0) { string[] genericNames = names.Select(genericName => $"<{genericName}>j__TPar").ToArray(); generics = tb.DefineGenericParameters(genericNames); foreach (GenericTypeParameterBuilder b in generics) { b.SetCustomAttribute(CompilerGeneratedAttributeBuilder); } } else { generics = new GenericTypeParameterBuilder[0]; } var fields = new FieldBuilder[names.Length]; // There are two for cycles because we want to have all the getter methods before all the other methods for (int i = 0; i < names.Length; i++) { // field fields[i] = tb.DefineField($"<{names[i]}>i__Field", generics[i].AsType(), FieldAttributes.Private | FieldAttributes.InitOnly); fields[i].SetCustomAttribute(DebuggerBrowsableAttributeBuilder); PropertyBuilder property = tb.DefineProperty(names[i], PropertyAttributes.None, CallingConventions.HasThis, generics[i].AsType(), EmptyTypes); // getter MethodBuilder getter = tb.DefineMethod($"get_{names[i]}", MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.SpecialName, CallingConventions.HasThis, generics[i].AsType(), null); getter.SetCustomAttribute(CompilerGeneratedAttributeBuilder); ILGenerator ilgeneratorGetter = getter.GetILGenerator(); ilgeneratorGetter.Emit(OpCodes.Ldarg_0); ilgeneratorGetter.Emit(OpCodes.Ldfld, fields[i]); ilgeneratorGetter.Emit(OpCodes.Ret); property.SetGetMethod(getter); // setter MethodBuilder setter = tb.DefineMethod($"set_{names[i]}", MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.SpecialName, CallingConventions.HasThis, null, new[] { generics[i].AsType() }); setter.SetCustomAttribute(CompilerGeneratedAttributeBuilder); // workaround for https://github.com/dotnet/corefx/issues/7792 setter.DefineParameter(1, ParameterAttributes.In, generics[i].Name); ILGenerator ilgeneratorSetter = setter.GetILGenerator(); ilgeneratorSetter.Emit(OpCodes.Ldarg_0); ilgeneratorSetter.Emit(OpCodes.Ldarg_1); ilgeneratorSetter.Emit(OpCodes.Stfld, fields[i]); ilgeneratorSetter.Emit(OpCodes.Ret); property.SetSetMethod(setter); } // ToString() MethodBuilder toString = tb.DefineMethod("ToString", MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.HideBySig, CallingConventions.HasThis, typeof(string), EmptyTypes); toString.SetCustomAttribute(DebuggerHiddenAttributeBuilder); ILGenerator ilgeneratorToString = toString.GetILGenerator(); ilgeneratorToString.DeclareLocal(typeof(StringBuilder)); ilgeneratorToString.Emit(OpCodes.Newobj, StringBuilderCtor); ilgeneratorToString.Emit(OpCodes.Stloc_0); // Equals MethodBuilder equals = tb.DefineMethod("Equals", MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.HideBySig, CallingConventions.HasThis, typeof(bool), new[] { typeof(object) }); equals.SetCustomAttribute(DebuggerHiddenAttributeBuilder); equals.DefineParameter(1, ParameterAttributes.In, "value"); ILGenerator ilgeneratorEquals = equals.GetILGenerator(); ilgeneratorEquals.DeclareLocal(tb.AsType()); ilgeneratorEquals.Emit(OpCodes.Ldarg_1); ilgeneratorEquals.Emit(OpCodes.Isinst, tb.AsType()); ilgeneratorEquals.Emit(OpCodes.Stloc_0); ilgeneratorEquals.Emit(OpCodes.Ldloc_0); Label equalsLabel = ilgeneratorEquals.DefineLabel(); // GetHashCode() MethodBuilder getHashCode = tb.DefineMethod("GetHashCode", MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.HideBySig, CallingConventions.HasThis, typeof(int), EmptyTypes); getHashCode.SetCustomAttribute(DebuggerHiddenAttributeBuilder); ILGenerator ilgeneratorGetHashCode = getHashCode.GetILGenerator(); ilgeneratorGetHashCode.DeclareLocal(typeof(int)); if (names.Length == 0) { ilgeneratorGetHashCode.Emit(OpCodes.Ldc_I4_0); } else { // As done by Roslyn // Note that initHash can vary, because string.GetHashCode() isn't "stable" for different compilation of the code int initHash = 0; for (int i = 0; i < names.Length; i++) { initHash = unchecked (initHash * (-1521134295) + fields[i].Name.GetHashCode()); } // Note that the CSC seems to generate a different seed for every anonymous class ilgeneratorGetHashCode.Emit(OpCodes.Ldc_I4, initHash); } for (int i = 0; i < names.Length; i++) { Type equalityComparerT = EqualityComparer.MakeGenericType(generics[i].AsType()); // Equals() MethodInfo equalityComparerTDefault = TypeBuilder.GetMethod(equalityComparerT, EqualityComparerDefault); MethodInfo equalityComparerTEquals = TypeBuilder.GetMethod(equalityComparerT, EqualityComparerEquals); // Illegal one-byte branch at position: 9. Requested branch was: 143. // So replace OpCodes.Brfalse_S to OpCodes.Brfalse ilgeneratorEquals.Emit(OpCodes.Brfalse, equalsLabel); ilgeneratorEquals.Emit(OpCodes.Call, equalityComparerTDefault); ilgeneratorEquals.Emit(OpCodes.Ldarg_0); ilgeneratorEquals.Emit(OpCodes.Ldfld, fields[i]); ilgeneratorEquals.Emit(OpCodes.Ldloc_0); ilgeneratorEquals.Emit(OpCodes.Ldfld, fields[i]); ilgeneratorEquals.Emit(OpCodes.Callvirt, equalityComparerTEquals); // GetHashCode(); MethodInfo equalityComparerTGetHashCode = TypeBuilder.GetMethod(equalityComparerT, EqualityComparerGetHashCode); ilgeneratorGetHashCode.Emit(OpCodes.Stloc_0); ilgeneratorGetHashCode.Emit(OpCodes.Ldc_I4, -1521134295); ilgeneratorGetHashCode.Emit(OpCodes.Ldloc_0); ilgeneratorGetHashCode.Emit(OpCodes.Mul); ilgeneratorGetHashCode.Emit(OpCodes.Call, equalityComparerTDefault); ilgeneratorGetHashCode.Emit(OpCodes.Ldarg_0); ilgeneratorGetHashCode.Emit(OpCodes.Ldfld, fields[i]); ilgeneratorGetHashCode.Emit(OpCodes.Callvirt, equalityComparerTGetHashCode); ilgeneratorGetHashCode.Emit(OpCodes.Add); // ToString(); ilgeneratorToString.Emit(OpCodes.Ldloc_0); ilgeneratorToString.Emit(OpCodes.Ldstr, i == 0 ? $"{{ {names[i]} = " : $", {names[i]} = "); ilgeneratorToString.Emit(OpCodes.Callvirt, StringBuilderAppendString); ilgeneratorToString.Emit(OpCodes.Pop); ilgeneratorToString.Emit(OpCodes.Ldloc_0); ilgeneratorToString.Emit(OpCodes.Ldarg_0); ilgeneratorToString.Emit(OpCodes.Ldfld, fields[i]); ilgeneratorToString.Emit(OpCodes.Box, generics[i].AsType()); ilgeneratorToString.Emit(OpCodes.Callvirt, StringBuilderAppendObject); ilgeneratorToString.Emit(OpCodes.Pop); } // Only create the default and with params constructor when there are any params. // Otherwise default constructor is not needed because it matches the default // one provided by the runtime when no constructor is present if (createParameterCtor && names.Any()) { // .ctor default ConstructorBuilder constructorDef = tb.DefineConstructor(MethodAttributes.Public | MethodAttributes.HideBySig, CallingConventions.HasThis, EmptyTypes); constructorDef.SetCustomAttribute(DebuggerHiddenAttributeBuilder); ILGenerator ilgeneratorConstructorDef = constructorDef.GetILGenerator(); ilgeneratorConstructorDef.Emit(OpCodes.Ldarg_0); ilgeneratorConstructorDef.Emit(OpCodes.Call, ObjectCtor); ilgeneratorConstructorDef.Emit(OpCodes.Ret); // .ctor with params ConstructorBuilder constructor = tb.DefineConstructor(MethodAttributes.Public | MethodAttributes.HideBySig, CallingConventions.HasThis, generics.Select(p => p.AsType()).ToArray()); constructor.SetCustomAttribute(DebuggerHiddenAttributeBuilder); ILGenerator ilgeneratorConstructor = constructor.GetILGenerator(); ilgeneratorConstructor.Emit(OpCodes.Ldarg_0); ilgeneratorConstructor.Emit(OpCodes.Call, ObjectCtor); for (int i = 0; i < names.Length; i++) { constructor.DefineParameter(i + 1, ParameterAttributes.None, names[i]); ilgeneratorConstructor.Emit(OpCodes.Ldarg_0); if (i == 0) { ilgeneratorConstructor.Emit(OpCodes.Ldarg_1); } else if (i == 1) { ilgeneratorConstructor.Emit(OpCodes.Ldarg_2); } else if (i == 2) { ilgeneratorConstructor.Emit(OpCodes.Ldarg_3); } else if (i < 255) { ilgeneratorConstructor.Emit(OpCodes.Ldarg_S, (byte)(i + 1)); } else { // Ldarg uses a ushort, but the Emit only accepts short, so we use a unchecked(...), cast to short and let the CLR interpret it as ushort. ilgeneratorConstructor.Emit(OpCodes.Ldarg, unchecked ((short)(i + 1))); } ilgeneratorConstructor.Emit(OpCodes.Stfld, fields[i]); } ilgeneratorConstructor.Emit(OpCodes.Ret); } // Equals() if (names.Length == 0) { ilgeneratorEquals.Emit(OpCodes.Ldnull); ilgeneratorEquals.Emit(OpCodes.Ceq); ilgeneratorEquals.Emit(OpCodes.Ldc_I4_0); ilgeneratorEquals.Emit(OpCodes.Ceq); } else { ilgeneratorEquals.Emit(OpCodes.Ret); ilgeneratorEquals.MarkLabel(equalsLabel); ilgeneratorEquals.Emit(OpCodes.Ldc_I4_0); } ilgeneratorEquals.Emit(OpCodes.Ret); // GetHashCode() ilgeneratorGetHashCode.Emit(OpCodes.Stloc_0); ilgeneratorGetHashCode.Emit(OpCodes.Ldloc_0); ilgeneratorGetHashCode.Emit(OpCodes.Ret); // ToString() ilgeneratorToString.Emit(OpCodes.Ldloc_0); ilgeneratorToString.Emit(OpCodes.Ldstr, names.Length == 0 ? "{ }" : " }"); ilgeneratorToString.Emit(OpCodes.Callvirt, StringBuilderAppendString); ilgeneratorToString.Emit(OpCodes.Pop); ilgeneratorToString.Emit(OpCodes.Ldloc_0); ilgeneratorToString.Emit(OpCodes.Callvirt, ObjectToString); ilgeneratorToString.Emit(OpCodes.Ret); type = tb.CreateType(); type = GeneratedTypes.GetOrAdd(key, type); } } } if (types.Length != 0) { type = type.MakeGenericType(types); } return(type); }
/// <summary> /// Implements the specified Interface on a given SysComponent source. Outputs the instanced type /// with properties copied from the specified source /// </summary> /// <param name="Interface">Interface Type parameter, can be inherited type</param> /// <param name="source">The instance containing the loaded model</param> /// <returns></returns> public static object DynamicInterfaceImplementation(Type Interface, SysComponent source) { Type newType = null; //Try to retrieve earlier implementation of the specified interface if (Implementations.TryGetValue(Interface, out newType)) { //Retrieve constructor parameters to be used in the new type instance if (Parameters.TryGetValue(newType, out List <TypeHelper> parameters)) { } //Instantiate the new type, using the results from GenerateParameters with the found constructor //GenerateParameters returns a List of delegates, used to bind methods to the model. var instance = Activator.CreateInstance(newType, GenerateParameters(parameters, source, ref newType).ToArray()); if (source == null) { return(instance); } else { return(BindToInstance(source, (ISysComponent)instance)); } } else { var name = Guid.NewGuid().ToString(); AssemblyBuilder assembly = AppDomain.CurrentDomain.DefineDynamicAssembly(new AssemblyName(name), AssemblyBuilderAccess.Run); ModuleBuilder module = assembly.DefineDynamicModule(name); TypeBuilder type = module.DefineType(typeof(SysComponent).Name + "_" + Interface.Name, TypeAttributes.Public, typeof(SysComponent)); ConstructorBuilder cstrBuilder = type.DefineConstructor(MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName, CallingConventions.Standard, GetConstructorParams(Interface)); var cstrGenerator = cstrBuilder.GetILGenerator(); //Load "This" instance reference cstrGenerator.Emit(OpCodes.Ldarg_0); //Call the default constructor for the type cstrGenerator.Emit(OpCodes.Call, typeof(object).GetConstructor(Type.EmptyTypes)); var fieldsList = new List <string>(); var paramList = new List <TypeHelper>(); Type[] interfaces = Interface.GetInterfaces(); var index = 0; foreach (var ancestor in interfaces) { ImplementInterface(ancestor, ref fieldsList, ref type, ref cstrBuilder, ref cstrGenerator, ref paramList, ref index); } ImplementInterface(Interface, ref fieldsList, ref type, ref cstrBuilder, ref cstrGenerator, ref paramList, ref index); //Return from the constructor cstrGenerator.Emit(OpCodes.Ret); newType = type.CreateType(); Implementations.Add(Interface, newType); Parameters.Add(newType, paramList); var parameterList = new List <dynamic>(); parameterList = GenerateParameters(paramList, source, ref newType); var instance = Activator.CreateInstance(newType, parameterList.ToArray()); if (source == null) { return(instance); } else { return(BindToInstance(source, (ISysComponent)instance)); //return BindToInstance(Interface, ret); } } }
private static CreateTypeResult CreateProxyType(Type proxyDefinitionType, Type targetType) { lock (_locker) { try { // Define parent type, interface types Type parentType; TypeAttributes typeAttributes; Type[] interfaceTypes; if (proxyDefinitionType.IsInterface || proxyDefinitionType.IsValueType) { // If the proxy type definition is an interface we create an struct proxy // If the proxy type definition is an struct then we use that struct to copy the values from the target type parentType = typeof(ValueType); typeAttributes = TypeAttributes.Public | TypeAttributes.AnsiClass | TypeAttributes.BeforeFieldInit | TypeAttributes.SequentialLayout | TypeAttributes.Sealed | TypeAttributes.Serializable; if (proxyDefinitionType.IsInterface) { interfaceTypes = new[] { proxyDefinitionType, typeof(IDuckType) }; } else { interfaceTypes = new[] { typeof(IDuckType) }; } } else { // If the proxy type definition is a class then we create a class proxy parentType = proxyDefinitionType; typeAttributes = TypeAttributes.Public | TypeAttributes.Class | TypeAttributes.AutoClass | TypeAttributes.AnsiClass | TypeAttributes.BeforeFieldInit | TypeAttributes.AutoLayout | TypeAttributes.Sealed; interfaceTypes = new[] { typeof(IDuckType) }; } // Gets the module builder var moduleBuilder = GetModuleBuilder(targetType, (targetType.IsPublic || targetType.IsNestedPublic) && (proxyDefinitionType.IsPublic || proxyDefinitionType.IsNestedPublic)); // Ensure visibility EnsureTypeVisibility(moduleBuilder, targetType); EnsureTypeVisibility(moduleBuilder, proxyDefinitionType); string assembly = string.Empty; if (targetType.Assembly != null) { // Include target assembly name and public token. AssemblyName asmName = targetType.Assembly.GetName(); assembly = asmName.Name; byte[] pbToken = asmName.GetPublicKeyToken(); assembly += "__" + BitConverter.ToString(pbToken).Replace("-", string.Empty); assembly = assembly.Replace(".", "_").Replace("+", "__"); } // Create a valid type name that can be used as a member of a class. (BenchmarkDotNet fails if is an invalid name) string proxyTypeName = $"{assembly}.{targetType.FullName.Replace(".", "_").Replace("+", "__")}.{proxyDefinitionType.FullName.Replace(".", "_").Replace("+", "__")}_{++_typeCount}"; // Create Type TypeBuilder proxyTypeBuilder = moduleBuilder.DefineType( proxyTypeName, typeAttributes, parentType, interfaceTypes); // Create IDuckType and IDuckTypeSetter implementations FieldInfo instanceField = CreateIDuckTypeImplementation(proxyTypeBuilder, targetType); // Define .ctor to store the instance field ConstructorBuilder ctorBuilder = proxyTypeBuilder.DefineConstructor( MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName, CallingConventions.Standard, new[] { instanceField.FieldType }); ILGenerator ctorIL = ctorBuilder.GetILGenerator(); ctorIL.Emit(OpCodes.Ldarg_0); ctorIL.Emit(OpCodes.Ldarg_1); ctorIL.Emit(OpCodes.Stfld, instanceField); ctorIL.Emit(OpCodes.Ret); if (proxyDefinitionType.IsValueType) { // Create Fields and Properties from the struct information CreatePropertiesFromStruct(proxyTypeBuilder, proxyDefinitionType, targetType, instanceField); // Create Type Type proxyType = proxyTypeBuilder.CreateTypeInfo().AsType(); return(new CreateTypeResult(proxyDefinitionType, proxyType, targetType, CreateStructCopyMethod(moduleBuilder, proxyDefinitionType, proxyType, targetType), null)); } else { // Create Fields and Properties CreateProperties(proxyTypeBuilder, proxyDefinitionType, targetType, instanceField); // Create Methods CreateMethods(proxyTypeBuilder, proxyDefinitionType, targetType, instanceField); // Create Type Type proxyType = proxyTypeBuilder.CreateTypeInfo().AsType(); return(new CreateTypeResult(proxyDefinitionType, proxyType, targetType, GetCreateProxyInstanceDelegate(moduleBuilder, proxyDefinitionType, proxyType, targetType), null)); } } catch (Exception ex) { return(new CreateTypeResult(proxyDefinitionType, null, targetType, null, ExceptionDispatchInfo.Capture(ex))); } } }
private Type CreateType(IEdmEntityType entityType) { // public class Address TypeBuilder typeBuilder = typeBuilders[entityType.Name]; var raisePropertyChanged = ImplementateNotifyPropertyChanged(typeBuilder); ConstructorBuilder constructor = typeBuilder.DefineConstructor(MethodAttributes.Public, CallingConventions.Standard, Type.EmptyTypes); ILGenerator constructorIL = constructor.GetILGenerator(); constructorIL.Emit(OpCodes.Ldarg_0); ConstructorInfo superConstructor = typeof(Object).GetConstructor(new Type[0]); constructorIL.Emit(OpCodes.Call, superConstructor); object[] keys = entityType.Key().Select(p => p.Name).ToArray(); var dataServiceKeyBuilder = new CustomAttributeBuilder(typeof(DataServiceKeyAttribute).GetConstructor(new[] { typeof(string) }), keys); typeBuilder.SetCustomAttribute(dataServiceKeyBuilder); //var entitySetName = entityType.Name.InflectTo().Pluralized; //var entitySetBuilder = new CustomAttributeBuilder(typeof(EntitySetAttribute).GetConstructor(new[] { typeof(string) }), new object[] { entitySetName }); //typeBuilder.SetCustomAttribute(entitySetBuilder); // Define fields and properties List <PropertyBuilder> propertyBuilders = new List <PropertyBuilder>(); foreach (var property in entityType.Properties()) { Type fieldType = null; var typeKind = property.Type.TypeKind(); switch (typeKind) { case EdmTypeKind.Primitive: fieldType = GetClrEquivalentType(property.Type); break; case EdmTypeKind.Entity: { string typeName = property.Type.AsEntity().EntityDefinition().Name; fieldType = typeBuilders[typeName]; } break; case EdmTypeKind.Collection: { string typeName = property.Type.AsCollection().ElementType().AsEntity().EntityDefinition().Name; var elementType = typeBuilders[typeName]; fieldType = typeof(DataServiceCollection <>).MakeGenericType(elementType); } break; } FieldBuilder field = typeBuilder.DefineField(property.Name, fieldType, FieldAttributes.Private); if (typeKind == EdmTypeKind.Collection) { constructorIL.Emit(OpCodes.Ldarg_0); ConstructorInfo ctorPrep = typeof(DataServiceCollection <>).GetConstructors().Single(c => c.GetParameters().Length == 2); ConstructorInfo ctor = TypeBuilder.GetConstructor(fieldType, ctorPrep); constructorIL.Emit(OpCodes.Ldnull); constructorIL.Emit(OpCodes.Ldc_I4_0); constructorIL.Emit(OpCodes.Newobj, ctor); constructorIL.Emit(OpCodes.Stfld, field); } propertyBuilders.Add(CreateProperty(typeBuilder, property.Name, field, raisePropertyChanged)); } constructorIL.Emit(OpCodes.Ret); // Override ToString OverrideToString(typeBuilder, propertyBuilders.ToArray()); return(typeBuilder); }
//==================================================================== // Creates a new managed type derived from a base type with any virtual // methods overriden to call out to python if the associated python // object has overriden the method. //==================================================================== internal static Type CreateDerivedType(string name, Type baseType, string namespaceStr, string assemblyName, string moduleName = "Python.Runtime.Dynamic.dll") { if (null != namespaceStr) { name = namespaceStr + "." + name; } if (null == assemblyName) { assemblyName = Assembly.GetExecutingAssembly().FullName; } ModuleBuilder moduleBuilder = GetModuleBuilder(assemblyName, moduleName); TypeBuilder typeBuilder; Type baseClass = baseType; List <Type> interfaces = new List <Type> { typeof(IPythonDerivedType) }; // if the base type is an interface then use System.Object as the base class // and add the base type to the list of interfaces this new class will implement. if (baseType.IsInterface) { interfaces.Add(baseType); baseClass = typeof(System.Object); } typeBuilder = moduleBuilder.DefineType(name, TypeAttributes.Public | TypeAttributes.Class, baseClass, interfaces.ToArray()); ILGenerator il; MethodBuilder mb; // add a field for storing the python object pointer FieldBuilder fb = typeBuilder.DefineField("__pyobj__", typeof(CLRObject), FieldAttributes.Public); // override any constructors ConstructorInfo[] constructors = baseClass.GetConstructors(); foreach (ConstructorInfo ctor in constructors) { ParameterInfo[] parameters = ctor.GetParameters(); Type[] parameterTypes = (from param in parameters select param.ParameterType).ToArray(); // create a method for calling the original constructor string baseCtorName = "_" + baseType.Name + "__cinit__"; mb = typeBuilder.DefineMethod(baseCtorName, MethodAttributes.Public | MethodAttributes.Final | MethodAttributes.HideBySig, typeof(void), parameterTypes); // emit the assembly for calling the original method using call instead of callvirt il = mb.GetILGenerator(); il.Emit(OpCodes.Ldarg_0); for (int i = 0; i < parameters.Length; ++i) { il.Emit(OpCodes.Ldarg, i + 1); } il.Emit(OpCodes.Call, ctor); il.Emit(OpCodes.Ret); // override the original method with a new one that dispatches to python ConstructorBuilder cb = typeBuilder.DefineConstructor(MethodAttributes.Public | MethodAttributes.ReuseSlot | MethodAttributes.HideBySig, ctor.CallingConvention, parameterTypes); il = cb.GetILGenerator(); il.DeclareLocal(typeof(Object[])); il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldstr, baseCtorName); il.Emit(OpCodes.Ldc_I4, parameters.Length); il.Emit(OpCodes.Newarr, typeof(System.Object)); il.Emit(OpCodes.Stloc_0); for (int i = 0; i < parameters.Length; ++i) { il.Emit(OpCodes.Ldloc_0); il.Emit(OpCodes.Ldc_I4, i); il.Emit(OpCodes.Ldarg, i + 1); if (parameterTypes[i].IsValueType) { il.Emit(OpCodes.Box, parameterTypes[i]); } il.Emit(OpCodes.Stelem, typeof(Object)); } il.Emit(OpCodes.Ldloc_0); il.Emit(OpCodes.Call, typeof(PythonDerivedType).GetMethod("InvokeCtor")); il.Emit(OpCodes.Ret); } // override any virtual methods MethodInfo[] methods = baseType.GetMethods(); foreach (MethodInfo method in methods) { if (!method.Attributes.HasFlag(MethodAttributes.Virtual) | method.Attributes.HasFlag(MethodAttributes.Final)) { continue; } ParameterInfo[] parameters = method.GetParameters(); Type[] parameterTypes = (from param in parameters select param.ParameterType).ToArray(); // create a method for calling the original method string baseMethodName = "_" + baseType.Name + "__" + method.Name; mb = typeBuilder.DefineMethod(baseMethodName, MethodAttributes.Public | MethodAttributes.Final | MethodAttributes.HideBySig, method.ReturnType, parameterTypes); // emit the assembly for calling the original method using call instead of callvirt il = mb.GetILGenerator(); il.Emit(OpCodes.Ldarg_0); for (int i = 0; i < parameters.Length; ++i) { il.Emit(OpCodes.Ldarg, i + 1); } il.Emit(OpCodes.Call, method); il.Emit(OpCodes.Ret); // override the original method with a new one that dispatches to python mb = typeBuilder.DefineMethod(method.Name, MethodAttributes.Public | MethodAttributes.ReuseSlot | MethodAttributes.Virtual | MethodAttributes.HideBySig, method.CallingConvention, method.ReturnType, parameterTypes); il = mb.GetILGenerator(); il.DeclareLocal(typeof(Object[])); il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldstr, method.Name); il.Emit(OpCodes.Ldstr, baseMethodName); il.Emit(OpCodes.Ldc_I4, parameters.Length); il.Emit(OpCodes.Newarr, typeof(System.Object)); il.Emit(OpCodes.Stloc_0); for (int i = 0; i < parameters.Length; ++i) { il.Emit(OpCodes.Ldloc_0); il.Emit(OpCodes.Ldc_I4, i); il.Emit(OpCodes.Ldarg, i + 1); if (parameterTypes[i].IsValueType) { il.Emit(OpCodes.Box, parameterTypes[i]); } il.Emit(OpCodes.Stelem, typeof(Object)); } il.Emit(OpCodes.Ldloc_0); if (method.ReturnType == typeof(void)) { il.Emit(OpCodes.Call, typeof(PythonDerivedType).GetMethod("InvokeMethodVoid")); } else { il.Emit(OpCodes.Call, typeof(PythonDerivedType).GetMethod("InvokeMethod").MakeGenericMethod(method.ReturnType)); } il.Emit(OpCodes.Ret); } // add the destructor so the python object created in the constructor gets destroyed mb = typeBuilder.DefineMethod("Finalize", MethodAttributes.Family | MethodAttributes.Virtual | MethodAttributes.HideBySig, CallingConventions.Standard, typeof(void), Type.EmptyTypes); il = mb.GetILGenerator(); il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Call, typeof(PythonDerivedType).GetMethod("Finalize")); il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Call, baseClass.GetMethod("Finalize", BindingFlags.NonPublic | BindingFlags.Instance)); il.Emit(OpCodes.Ret); Type type = typeBuilder.CreateType(); // scan the assembly so the newly added class can be imported Assembly assembly = Assembly.GetAssembly(type); AssemblyManager.ScanAssembly(assembly); return(type); }
//==================================================================== // GetDispatcher is responsible for creating a class that provides // an appropriate managed callback method for a given delegate type. //==================================================================== private Type GetDispatcher(Type dtype) { // If a dispatcher type for the given delegate type has already // been generated, get it from the cache. The cache maps delegate // types to generated dispatcher types. A possible optimization // for the future would be to generate dispatcher types based on // unique signatures rather than delegate types, since multiple // delegate types with the same sig could use the same dispatcher. Object item = cache[dtype]; if (item != null) { return((Type)item); } string name = "__" + dtype.FullName + "Dispatcher"; name = name.Replace('.', '_'); name = name.Replace('+', '_'); TypeBuilder tb = codeGenerator.DefineType(name, basetype); // Generate a constructor for the generated type that calls the // appropriate constructor of the Dispatcher base type. MethodAttributes ma = MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName; CallingConventions cc = CallingConventions.Standard; Type[] args = { ptrtype, typetype }; ConstructorBuilder cb = tb.DefineConstructor(ma, cc, args); ConstructorInfo ci = basetype.GetConstructor(args); ILGenerator il = cb.GetILGenerator(); il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldarg_1); il.Emit(OpCodes.Ldarg_2); il.Emit(OpCodes.Call, ci); il.Emit(OpCodes.Ret); // Method generation: we generate a method named "Invoke" on the // dispatcher type, whose signature matches the delegate type for // which it is generated. The method body simply packages the // arguments and hands them to the Dispatch() method, which deals // with converting the arguments, calling the Python method and // converting the result of the call. MethodInfo method = dtype.GetMethod("Invoke"); ParameterInfo[] pi = method.GetParameters(); Type[] signature = new Type[pi.Length]; for (int i = 0; i < pi.Length; i++) { signature[i] = pi[i].ParameterType; } MethodBuilder mb = tb.DefineMethod( "Invoke", MethodAttributes.Public, method.ReturnType, signature ); ConstructorInfo ctor = listtype.GetConstructor(Type.EmptyTypes); MethodInfo dispatch = basetype.GetMethod("Dispatch"); MethodInfo add = listtype.GetMethod("Add"); il = mb.GetILGenerator(); il.DeclareLocal(listtype); il.Emit(OpCodes.Newobj, ctor); il.Emit(OpCodes.Stloc_0); for (int c = 0; c < signature.Length; c++) { Type t = signature[c]; il.Emit(OpCodes.Ldloc_0); il.Emit(OpCodes.Ldarg_S, (byte)(c + 1)); if (t.IsValueType) { il.Emit(OpCodes.Box, t); } il.Emit(OpCodes.Callvirt, add); il.Emit(OpCodes.Pop); } il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldloc_0); il.Emit(OpCodes.Call, dispatch); if (method.ReturnType == voidtype) { il.Emit(OpCodes.Pop); } else if (method.ReturnType.IsValueType) { il.Emit(OpCodes.Unbox_Any, method.ReturnType); } il.Emit(OpCodes.Ret); Type disp = tb.CreateType(); cache[dtype] = disp; return(disp); }
public CodeGen DefineStaticConstructor() { ConstructorBuilder cb = _myType.DefineTypeInitializer(); return(CreateCodeGen(cb, cb.GetILGenerator(), ArrayUtils.EmptyTypes)); }
/// <summary> /// 创建 TCP 服务端 /// </summary> /// <param name="type"></param> /// <param name="attribute"></param> /// <param name="serverInterfaceType"></param> /// <param name="serverCallType"></param> /// <param name="constructorParameterTypes"></param> /// <param name="methods"></param> /// <returns></returns> internal Type Build(Type type, ServerAttribute attribute, Type serverInterfaceType, Type serverCallType, Type[] constructorParameterTypes, Method <attributeType, methodAttributeType, serverSocketType>[] methods) { string serverIdentity = Interlocked.Increment(ref Metadata.Identity).toString(); TypeBuilder typeBuilder = AutoCSer.Emit.Builder.Module.Builder.DefineType(Metadata.ServerTypeName + ".Emit." + type.FullName, TypeAttributes.Class | TypeAttributes.Sealed, Metadata.ServerType); FieldBuilder valueFieldBuilder = typeBuilder.DefineField("_value_", typeof(object), FieldAttributes.Private | FieldAttributes.InitOnly); ConstructorBuilder constructorBuilder = typeBuilder.DefineConstructor(MethodAttributes.Public, CallingConventions.Standard, constructorParameterTypes); ILGenerator constructorGenerator = constructorBuilder.GetILGenerator(); Label serverAttributeNotNull = constructorGenerator.DefineLabel(); bool isCallQueue = false; foreach (Method <attributeType, methodAttributeType, serverSocketType> method in methods) { if (method != null && (isCallQueue |= method.Attribute.ServerTaskType == TcpServer.ServerTaskType.Queue)) { break; } } #region base(attribute, verify, log, isCallQueue) constructorGenerator.Emit(OpCodes.Ldarg_0); constructorGenerator.Emit(OpCodes.Ldarg_1); constructorGenerator.Emit(OpCodes.Ldarg_2); constructorGenerator.Emit(OpCodes.Ldarg_S, 4); constructorGenerator.int32(isCallQueue ? 1 : 0); constructorGenerator.Emit(OpCodes.Call, Metadata.ServerConstructorInfo); #endregion #region _value_ = value; constructorGenerator.Emit(OpCodes.Ldarg_0); constructorGenerator.Emit(OpCodes.Ldarg_3); constructorGenerator.Emit(OpCodes.Stfld, valueFieldBuilder); #endregion constructorGenerator.Emit(OpCodes.Ret); ConstructorBuilder staticConstructorBuilder = typeBuilder.DefineConstructor(MethodAttributes.Public | MethodAttributes.Static, CallingConventions.Standard, null); ILGenerator staticConstructorGenerator = staticConstructorBuilder.GetILGenerator(); #region public override bool DoCommand(int index, AutoCSer.Net.TcpInternalSimpleServer.ServerSocket socket, ref SubArray<byte> data) MethodBuilder doCommandMethodBuilder = typeBuilder.DefineMethod("DoCommand", MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.HideBySig | MethodAttributes.ReuseSlot, typeof(bool), Metadata.DoCommandParameterTypes); #endregion ILGenerator doCommandGenerator = doCommandMethodBuilder.GetILGenerator(); doCommandGenerator.DeclareLocal(typeof(int)); Label doCommandReturnLabel = doCommandGenerator.DefineLabel(); Label[] doCommandLabels = new Label[methods.Length]; int doCommandLabelIndex = 0; foreach (Method <attributeType, methodAttributeType, serverSocketType> method in methods) { doCommandLabels[doCommandLabelIndex++] = method == null ? doCommandReturnLabel : (method.DoCommandLabel = doCommandGenerator.DefineLabel()); } #region switch (index - @CommandStartIndex) doCommandGenerator.Emit(OpCodes.Ldarg_1); doCommandGenerator.int32(TcpServer.Server.CommandStartIndex); doCommandGenerator.Emit(OpCodes.Sub); doCommandGenerator.Emit(OpCodes.Stloc_0); doCommandGenerator.Emit(OpCodes.Ldloc_0); doCommandGenerator.Emit(OpCodes.Switch, doCommandLabels); doCommandGenerator.MarkLabel(doCommandReturnLabel); doCommandGenerator.int32(0); doCommandGenerator.Emit(OpCodes.Ret); #endregion Outputs = new TcpSimpleServer.OutputInfo[methods.Length]; FieldInfo outputsField = serverInterfaceType.GetField("Outputs", BindingFlags.Static | BindingFlags.NonPublic); foreach (Method <attributeType, methodAttributeType, serverSocketType> method in methods) { if (method != null) { FieldBuilder outputInfoFieldBuilder; if (method.OutputParameterType == null && !method.IsAsynchronousCallback) { outputInfoFieldBuilder = null; } else { TcpSimpleServer.OutputInfo outputInfo = new TcpSimpleServer.OutputInfo(); Outputs[method.Attribute.CommandIdentity] = outputInfo; if (method.OutputParameterType != null) { outputInfo.OutputParameterIndex = method.OutputParameterType.Index; if (attribute.IsSimpleSerialize) { outputInfo.IsSimpleSerializeOutputParamter = method.OutputParameterType.IsSimpleSerialize && SimpleSerialize.Serializer.IsType(method.ReturnType); } } #region private static readonly AutoCSer.Net.TcpSimpleServer.OutputInfo @MethodIdentityCommand = AutoCSer.Net.TcpInternalSimpleServer.Emit.Server<interfaceType>.Outputs[@CommandIdentity]; staticConstructorGenerator.Emit(OpCodes.Ldsfld, outputsField); staticConstructorGenerator.int32(method.Attribute.CommandIdentity); staticConstructorGenerator.Emit(OpCodes.Ldelem_Ref); staticConstructorGenerator.Emit(OpCodes.Stsfld, outputInfoFieldBuilder = typeBuilder.DefineField("_o" + method.Attribute.CommandIdentity.toString(), typeof(TcpServer.OutputInfo), FieldAttributes.Private | FieldAttributes.InitOnly | FieldAttributes.Static)); #endregion } ParameterInfo[] parameters = method.MethodInfo.GetParameters(); TypeBuilder serverCallTypeBuilder; FieldInfo returnTypeField = method.ReturnValueType == null ? null : (method.ReturnValueType == typeof(TcpServer.ReturnValue) ? TcpServer.Emit.ServerMetadata.ReturnValueTypeField : method.ReturnValueType.GetField(TcpServer.Emit.ServerMetadata.ReturnValueTypeField.Name, BindingFlags.Instance | BindingFlags.Public)); FieldInfo returnValueField = method.ReturnValueType == null ? null : method.ReturnValueType.GetField("Value", BindingFlags.Instance | BindingFlags.Public); if (method.IsMethodServerCall) { Type baseType = method.ParameterType == null ? Metadata.ServerCallType : serverCallType.MakeGenericType(method.ParameterType.Type); FieldInfo inputParameterField = method.ParameterType == null ? null : baseType.GetField("inputParameter", BindingFlags.Instance | BindingFlags.NonPublic); serverCallTypeBuilder = typeBuilder.DefineNestedType(Metadata.ServerCallTypeName + ".Emit." + serverIdentity + "_" + method.Attribute.CommandIdentity.toString(), TypeAttributes.Class | TypeAttributes.Sealed | TypeAttributes.NestedPublic, baseType); Type returnOutputType = method.OutputParameterType == null ? typeof(AutoCSer.Net.TcpServer.ReturnValue) : typeof(AutoCSer.Net.TcpServer.ReturnValue <>).MakeGenericType(method.OutputParameterType.Type); FieldInfo returnOutputValueField = method.OutputParameterType == null ? null : returnOutputType.GetField("Value", BindingFlags.Instance | BindingFlags.Public); Type returnOutputRefType = returnOutputType.MakeByRefType(); #region private void get(ref AutoCSer.Net.TcpServer.ReturnValue<@OutputParameterTypeName> value) MethodBuilder getMethodBuilder = serverCallTypeBuilder.DefineMethod("get", MethodAttributes.Private, typeof(void), new Type[] { returnOutputRefType }); #endregion ILGenerator getGenerator = getMethodBuilder.GetILGenerator(); Label getReturnLabel = getGenerator.DefineLabel(); LocalBuilder exceptionErrorLocalBuilder = getGenerator.DeclareLocal(typeof(Exception)); #region try getGenerator.BeginExceptionBlock(); #endregion #region @MethodReturnType.FullName @ReturnName = serverValue.@MethodName(Socket, inputParameter.@ParameterName); LocalBuilder returnLocalBuilder = method.IsReturnType ? getGenerator.DeclareLocal(method.ReturnValueType ?? method.ReturnType) : null; getGenerator.Emit(OpCodes.Ldarg_0); getGenerator.Emit(OpCodes.Ldfld, Metadata.ServerCallServerValueField); foreach (ParameterInfo parameter in parameters) { if (SimpleParameterType.IsInputParameter(parameter)) { getGenerator.Emit(OpCodes.Ldarg_0); getGenerator.Emit(OpCodes.Ldflda, inputParameterField); getGenerator.Emit(parameter.ParameterType.IsByRef ? OpCodes.Ldflda : OpCodes.Ldfld, method.ParameterType.GetField(parameter.Name)); } else if (parameter.IsOut) { getGenerator.Emit(OpCodes.Ldarg_1); getGenerator.Emit(OpCodes.Ldflda, returnOutputValueField); getGenerator.Emit(OpCodes.Ldflda, method.OutputParameterType.GetField(parameter.Name)); } else if (parameter.ParameterType == Metadata.SocketType) { getGenerator.Emit(OpCodes.Ldarg_0); getGenerator.Emit(OpCodes.Ldfld, Metadata.ServerCallSocketField); } else { getGenerator.Emit(OpCodes.Ldnull); } } getGenerator.call(method.MethodInfo); if (method.IsReturnType) { getGenerator.Emit(OpCodes.Stloc_S, returnLocalBuilder); } #endregion FieldInfo returnValueTypeField = method.OutputParameterType == null ? TcpServer.Emit.ServerMetadata.ReturnValueTypeField : returnOutputType.GetField(TcpServer.Emit.ServerMetadata.ReturnValueTypeField.Name, BindingFlags.Instance | BindingFlags.Public); if (method.OutputParameterType == null) { if (method.ReturnValueType != null) { Label returnTypeErrorLabel = getGenerator.DefineLabel(); #region if(@ReturnName.Type != AutoCSer.Net.TcpServer.ReturnType.Success) getGenerator.Emit(OpCodes.Ldloca_S, returnLocalBuilder); getGenerator.Emit(OpCodes.Ldfld, returnTypeField); getGenerator.int32((byte)AutoCSer.Net.TcpServer.ReturnType.Success); getGenerator.Emit(OpCodes.Beq_S, returnTypeErrorLabel); #endregion #region value.Type = @ReturnName.Type; getGenerator.Emit(OpCodes.Ldarg_1); getGenerator.Emit(OpCodes.Ldloca_S, returnLocalBuilder); getGenerator.Emit(OpCodes.Ldfld, returnTypeField); getGenerator.Emit(OpCodes.Stfld, returnValueTypeField); #endregion getGenerator.Emit(OpCodes.Leave_S, getReturnLabel); getGenerator.MarkLabel(returnTypeErrorLabel); } #region value.Type = AutoCSer.Net.TcpServer.ReturnType.Success; getGenerator.Emit(OpCodes.Ldarg_1); getGenerator.int32((byte)AutoCSer.Net.TcpServer.ReturnType.Success); getGenerator.Emit(OpCodes.Stfld, returnValueTypeField); #endregion getGenerator.Emit(OpCodes.Leave_S, getReturnLabel); } else { Label returnTypeErrorLabel; if (method.ReturnValueType == null) { returnTypeErrorLabel = default(Label); } else { #region if(@ReturnName.Type != AutoCSer.Net.TcpServer.ReturnType.Success) getGenerator.Emit(OpCodes.Ldloca_S, returnLocalBuilder); getGenerator.Emit(OpCodes.Ldfld, returnTypeField); getGenerator.int32((byte)AutoCSer.Net.TcpServer.ReturnType.Success); getGenerator.Emit(OpCodes.Bne_Un, returnTypeErrorLabel = getGenerator.DefineLabel()); #endregion } if (method.Attribute.IsVerifyMethod) { Label verifyEndLabel = getGenerator.DefineLabel(); #region if (@ReturnName / @ReturnName.Value) if (method.ReturnValueType == null) { getGenerator.Emit(OpCodes.Ldloc_S, returnLocalBuilder); } else { getGenerator.Emit(OpCodes.Ldloca_S, returnLocalBuilder); getGenerator.Emit(OpCodes.Ldfld, returnValueField); } getGenerator.Emit(OpCodes.Brfalse_S, verifyEndLabel); #endregion #region Socket.SetVerifyMethod(); getGenerator.Emit(OpCodes.Ldarg_0); getGenerator.Emit(OpCodes.Ldfld, Metadata.ServerCallSocketField); getGenerator.call(ServerMetadata.ServerSocketSetVerifyMethodMethod); #endregion getGenerator.MarkLabel(verifyEndLabel); } LocalBuilder valueLocalBuilder = getGenerator.DeclareLocal(method.OutputParameterType.Type); #region value.Value.@ParameterName = inputParameter.@ParameterName; foreach (ParameterInfo parameter in method.OutputParameters) { if (!parameter.IsOut) { getGenerator.Emit(OpCodes.Ldarg_1); getGenerator.Emit(OpCodes.Ldflda, returnOutputValueField); getGenerator.Emit(OpCodes.Ldarg_0); getGenerator.Emit(OpCodes.Ldflda, inputParameterField); getGenerator.Emit(OpCodes.Ldfld, method.ParameterType.GetField(parameter.Name)); getGenerator.Emit(OpCodes.Stfld, method.OutputParameterType.GetField(parameter.Name)); } } #endregion if (method.ReturnType != typeof(void)) { #region value.Value.@ReturnName = @ReturnName / @ReturnName.Value; getGenerator.Emit(OpCodes.Ldarg_1); getGenerator.Emit(OpCodes.Ldflda, returnOutputValueField); if (method.ReturnValueType == null) { getGenerator.Emit(OpCodes.Ldloc_S, returnLocalBuilder); } else { getGenerator.Emit(OpCodes.Ldloca_S, returnLocalBuilder); getGenerator.Emit(OpCodes.Ldfld, returnValueField); } getGenerator.Emit(OpCodes.Stfld, method.OutputParameterType.GetField(TcpServer.ReturnValue.RetParameterName)); #endregion } #region value.Type = AutoCSer.Net.TcpServer.ReturnType.Success; getGenerator.Emit(OpCodes.Ldarg_1); getGenerator.int32((byte)AutoCSer.Net.TcpServer.ReturnType.Success); getGenerator.Emit(OpCodes.Stfld, returnValueTypeField); #endregion getGenerator.Emit(OpCodes.Leave_S, getReturnLabel); if (method.ReturnValueType != null) { getGenerator.MarkLabel(returnTypeErrorLabel); #region value.Type = @ReturnName.Type; getGenerator.Emit(OpCodes.Ldarg_1); getGenerator.Emit(OpCodes.Ldloca_S, returnLocalBuilder); getGenerator.Emit(OpCodes.Ldfld, returnTypeField); getGenerator.Emit(OpCodes.Stfld, returnValueTypeField); #endregion getGenerator.Emit(OpCodes.Leave_S, getReturnLabel); } } #region catch (Exception error) getGenerator.BeginCatchBlock(typeof(Exception)); getGenerator.Emit(OpCodes.Stloc_S, exceptionErrorLocalBuilder); #endregion #region value.Type = AutoCSer.Net.TcpServer.ReturnType.ServerException; getGenerator.Emit(OpCodes.Ldarg_1); getGenerator.int32((byte)AutoCSer.Net.TcpServer.ReturnType.ServerException); getGenerator.Emit(OpCodes.Stfld, returnValueTypeField); #endregion #region Socket.Log(error); getGenerator.Emit(OpCodes.Ldarg_0); getGenerator.Emit(OpCodes.Ldfld, Metadata.ServerCallSocketField); getGenerator.Emit(OpCodes.Ldloc_S, exceptionErrorLocalBuilder); getGenerator.call(Metadata.ServerSocketLogMethod); #endregion getGenerator.Emit(OpCodes.Leave_S, getReturnLabel); #region try end getGenerator.EndExceptionBlock(); #endregion getGenerator.MarkLabel(getReturnLabel); getGenerator.Emit(OpCodes.Ret); #region public override void Call() MethodBuilder callMethodBuilder = serverCallTypeBuilder.DefineMethod("Call", MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.HideBySig | MethodAttributes.ReuseSlot, typeof(void), null); #endregion ILGenerator callGenerator = callMethodBuilder.GetILGenerator(); #region AutoCSer.Net.TcpInternalSimpleServer.ServerSocket socket = Socket; LocalBuilder socketBuilder = callGenerator.DeclareLocal(typeof(serverSocketType)); getGenerator.Emit(OpCodes.Ldarg_0); getGenerator.Emit(OpCodes.Ldfld, Metadata.ServerCallSocketField); callGenerator.Emit(OpCodes.Stloc_S, socketBuilder); #endregion #region AutoCSer.Net.TcpServer.ReturnValue<@OutputParameterTypeName> value = new AutoCSer.Net.TcpServer.ReturnValue<@OutputParameterTypeName>(); LocalBuilder valueBuilder = callGenerator.DeclareLocal(returnOutputType); if (method.OutputParameterType == null || method.Attribute.IsInitobj || method.OutputParameterType.IsInitobj) { callGenerator.Emit(OpCodes.Ldloca_S, valueBuilder); callGenerator.Emit(OpCodes.Initobj, returnOutputType); } else { callGenerator.Emit(OpCodes.Ldloca_S, valueBuilder); callGenerator.int32(0); callGenerator.Emit(OpCodes.Stfld, returnValueTypeField); } #endregion #region get(ref value); callGenerator.Emit(OpCodes.Ldarg_0); callGenerator.Emit(OpCodes.Ldloca_S, valueBuilder); callGenerator.call(getMethodBuilder); #endregion #region push(this); callGenerator.Emit(OpCodes.Ldarg_0); callGenerator.Emit(OpCodes.Ldarg_0); callGenerator.call((method.ParameterType == null ? Metadata.ServerCallPushMethod : serverCallType.MakeGenericType(method.ParameterType.Type).GetMethod("push", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.DeclaredOnly)).MakeGenericMethod(serverCallTypeBuilder)); #endregion if (method.OutputParameterType == null) { #region socket.SendAsync(value.Type); callGenerator.Emit(OpCodes.Ldloc_S, socketBuilder); callGenerator.Emit(OpCodes.Ldloca_S, valueBuilder); callGenerator.Emit(OpCodes.Ldfld, returnValueTypeField); callGenerator.call(Metadata.ServerSocketSendAsyncMethod); callGenerator.Emit(OpCodes.Pop); #endregion } else { #region socket.SendAsync(@MethodIdentityCommand, ref value); callGenerator.Emit(OpCodes.Ldloc_S, socketBuilder); callGenerator.Emit(OpCodes.Ldsfld, outputInfoFieldBuilder); callGenerator.Emit(OpCodes.Ldloca_S, valueBuilder); callGenerator.call(Metadata.ServerSocketSendAsyncOutputMethod.MakeGenericMethod(method.OutputParameterType.Type)); callGenerator.Emit(OpCodes.Pop); #endregion } callGenerator.Emit(OpCodes.Ret); serverCallTypeBuilder.CreateType(); } else { serverCallTypeBuilder = null; } #region private bool @MethodIndexName(AutoCSer.Net.TcpInternalSimpleServer.ServerSocket socket, ref SubArray<byte> data) MethodBuilder methodBuilder = typeBuilder.DefineMethod("_m" + method.Attribute.CommandIdentity.toString(), MethodAttributes.Private, typeof(bool), Metadata.MethodParameterTypes); #endregion ILGenerator methodGenerator = methodBuilder.GetILGenerator(); if (method.Attribute.IsExpired) { if (method.OutputParameterType == null) { #region return socket.Send(AutoCSer.Net.TcpServer.ReturnType.VersionExpired); methodGenerator.Emit(OpCodes.Ldarg_1); methodGenerator.int32((byte)AutoCSer.Net.TcpServer.ReturnType.VersionExpired); methodGenerator.call(Metadata.ServerSocketSendReturnTypeMethod); methodGenerator.Emit(OpCodes.Ret); #endregion } else { #region return socket.SendOutput(AutoCSer.Net.TcpServer.ReturnType.VersionExpired); methodGenerator.Emit(OpCodes.Ldarg_1); methodGenerator.int32((byte)AutoCSer.Net.TcpServer.ReturnType.VersionExpired); methodGenerator.call(Metadata.ServerSocketSendOutputReturnTypeMethod); methodGenerator.Emit(OpCodes.Ret); #endregion } } else { Label pushLabel = methodGenerator.DefineLabel(), returnLable = methodGenerator.DefineLabel(); #region bool isReturnLocalBuilder = false; LocalBuilder isReturnLocalBuilder = methodGenerator.DeclareLocal(typeof(bool)); methodGenerator.int32(0); methodGenerator.Emit(OpCodes.Stloc_S, isReturnLocalBuilder); #endregion #region AutoCSer.Net.TcpServer.ReturnType returnType = AutoCSer.Net.TcpServer.ReturnType.Unknown; LocalBuilder returnTypeLocalBuilder = methodGenerator.DeclareLocal(typeof(AutoCSer.Net.TcpServer.ReturnType)); methodGenerator.int32((byte)AutoCSer.Net.TcpServer.ReturnType.Unknown); methodGenerator.Emit(OpCodes.Stloc_S, returnTypeLocalBuilder); #endregion #region try methodGenerator.BeginExceptionBlock(); #endregion LocalBuilder parameterLocalBuilder, outputParameterLocalBuilder = null; Label serverDeSerializeErrorLabel; if (method.ParameterType == null) { parameterLocalBuilder = null; serverDeSerializeErrorLabel = default(Label); } else { #region @InputParameterTypeName inputParameter = new @InputParameterTypeName(); parameterLocalBuilder = methodGenerator.DeclareLocal(method.ParameterType.Type); if (method.Attribute.IsInitobj || method.ParameterType.IsInitobj) { methodGenerator.Emit(OpCodes.Ldloca_S, parameterLocalBuilder); methodGenerator.Emit(OpCodes.Initobj, method.ParameterType.Type); } #endregion #region if (socket.DeSerialize(ref data, ref inputParameter)) methodGenerator.Emit(OpCodes.Ldarg_1); methodGenerator.Emit(OpCodes.Ldarg_2); methodGenerator.Emit(OpCodes.Ldloca_S, parameterLocalBuilder); methodGenerator.int32(method.ParameterType.IsSimpleSerialize ? 1 : 0); methodGenerator.call(ServerMetadata.ServerSocketDeSerializeMethod.MakeGenericMethod(method.ParameterType.Type)); methodGenerator.Emit(OpCodes.Brfalse, serverDeSerializeErrorLabel = methodGenerator.DefineLabel()); #endregion } if (method.IsMethodServerCall) { #region @MethodStreamName.Call(socket, _value_, @ServerTask, ref inputParameter); methodGenerator.Emit(OpCodes.Ldarg_1); methodGenerator.Emit(OpCodes.Ldarg_0); methodGenerator.Emit(OpCodes.Ldfld, valueFieldBuilder); methodGenerator.int32((byte)method.ServerTask); if (method.ParameterType == null) { methodGenerator.call(Metadata.ServerCallCallMethod.MakeGenericMethod(serverCallTypeBuilder)); } else { methodGenerator.Emit(OpCodes.Ldloca_S, parameterLocalBuilder); methodGenerator.call(serverCallType.MakeGenericType(method.ParameterType.Type).GetMethod("Call", BindingFlags.Static | BindingFlags.Public | BindingFlags.DeclaredOnly).MakeGenericMethod(serverCallTypeBuilder)); } #endregion #region isReturnLocalBuilder = true; methodGenerator.int32(1); methodGenerator.Emit(OpCodes.Stloc_S, isReturnLocalBuilder); #endregion } else { if (method.OutputParameterType != null) { #region @OutputParameterTypeName outputParameter = new @OutputParameterTypeName(); outputParameterLocalBuilder = methodGenerator.DeclareLocal(method.OutputParameterType.Type); if (method.Attribute.IsInitobj || method.OutputParameterType.IsInitobj) { methodGenerator.Emit(OpCodes.Ldloca_S, outputParameterLocalBuilder); methodGenerator.Emit(OpCodes.Initobj, method.OutputParameterType.Type); } #endregion } #region @MethodReturnType.FullName @ReturnName = _value_.@MethodName(socket, inputParameter.@ParameterName); LocalBuilder returnLocalBuilder = method.IsReturnType ? methodGenerator.DeclareLocal(method.ReturnValueType ?? method.ReturnType) : null; methodGenerator.Emit(OpCodes.Ldarg_0); methodGenerator.Emit(OpCodes.Ldfld, valueFieldBuilder); foreach (ParameterInfo parameter in parameters) { if (SimpleParameterType.IsInputParameter(parameter)) { methodGenerator.Emit(OpCodes.Ldloca_S, parameterLocalBuilder); methodGenerator.Emit(parameter.ParameterType.IsByRef ? OpCodes.Ldflda : OpCodes.Ldfld, method.ParameterType.GetField(parameter.Name)); } else if (parameter.IsOut) { methodGenerator.Emit(OpCodes.Ldloca_S, outputParameterLocalBuilder); methodGenerator.Emit(OpCodes.Ldflda, method.OutputParameterType.GetField(parameter.Name)); } else if (parameter.ParameterType == Metadata.SocketType) { methodGenerator.Emit(OpCodes.Ldarg_1); } else { methodGenerator.Emit(OpCodes.Ldnull); } } methodGenerator.call(method.MethodInfo); if (method.IsReturnType) { methodGenerator.Emit(OpCodes.Stloc_S, returnLocalBuilder); } #endregion if (method.OutputParameterType == null) { if (method.ReturnValueType == null) { #region return socket.Send(); methodGenerator.Emit(OpCodes.Ldarg_1); methodGenerator.call(Metadata.ServerSocketSendMethod); methodGenerator.Emit(OpCodes.Stloc_S, isReturnLocalBuilder); #endregion } else { #region return socket.Send(@ReturnName.Type); methodGenerator.Emit(OpCodes.Ldarg_1); methodGenerator.Emit(OpCodes.Ldloca_S, returnLocalBuilder); methodGenerator.Emit(OpCodes.Ldfld, returnTypeField); methodGenerator.call(Metadata.ServerSocketSendReturnTypeMethod); methodGenerator.Emit(OpCodes.Stloc_S, isReturnLocalBuilder); #endregion } } else { Label returnTypeErrorLabel; if (method.ReturnValueType == null) { returnTypeErrorLabel = default(Label); } else { #region if(@ReturnName.Type == AutoCSer.Net.TcpServer.ReturnType.Success) methodGenerator.Emit(OpCodes.Ldloca_S, returnLocalBuilder); methodGenerator.Emit(OpCodes.Ldfld, returnTypeField); methodGenerator.int32((byte)AutoCSer.Net.TcpServer.ReturnType.Success); methodGenerator.Emit(OpCodes.Bne_Un, returnTypeErrorLabel = methodGenerator.DefineLabel()); #endregion } if (method.Attribute.IsVerifyMethod) { Label verifyEndLabel = methodGenerator.DefineLabel(); #region if (@ReturnName / @ReturnName.Value) if (method.ReturnValueType == null) { methodGenerator.Emit(OpCodes.Ldloc_S, returnLocalBuilder); } else { methodGenerator.Emit(OpCodes.Ldloca_S, returnLocalBuilder); methodGenerator.Emit(OpCodes.Ldfld, returnValueField); } methodGenerator.Emit(OpCodes.Brfalse_S, verifyEndLabel); #endregion #region socket.SetVerifyMethod(); methodGenerator.Emit(OpCodes.Ldarg_1); methodGenerator.call(ServerMetadata.ServerSocketSetVerifyMethodMethod); #endregion methodGenerator.MarkLabel(verifyEndLabel); } foreach (ParameterInfo parameter in method.OutputParameters) { if (!parameter.IsOut) { #region outputParameter.@ParameterName = inputParameter.@ParameterName methodGenerator.Emit(OpCodes.Ldloca_S, outputParameterLocalBuilder); methodGenerator.Emit(OpCodes.Ldloca_S, parameterLocalBuilder); methodGenerator.Emit(OpCodes.Ldfld, method.ParameterType.GetField(parameter.Name)); methodGenerator.Emit(OpCodes.Stfld, method.OutputParameterType.GetField(parameter.Name)); #endregion } } if (method.ReturnType != typeof(void)) { #region _outputParameter_.Ret = @ReturnName / @ReturnName.Value methodGenerator.Emit(OpCodes.Ldloca_S, outputParameterLocalBuilder); if (method.ReturnValueType == null) { methodGenerator.Emit(OpCodes.Ldloc_S, returnLocalBuilder); } else { methodGenerator.Emit(OpCodes.Ldloca_S, returnLocalBuilder); methodGenerator.Emit(OpCodes.Ldfld, returnValueField); } methodGenerator.Emit(OpCodes.Stfld, method.OutputParameterType.GetField(TcpServer.ReturnValue.RetParameterName)); #endregion } #region return socket.Send(@MethodIdentityCommand, ref outputParameter) methodGenerator.Emit(OpCodes.Ldarg_1); methodGenerator.Emit(OpCodes.Ldsfld, outputInfoFieldBuilder); methodGenerator.Emit(OpCodes.Ldloca_S, outputParameterLocalBuilder); methodGenerator.call(Metadata.ServerSocketSendOutputMethod.MakeGenericMethod(method.OutputParameterType.Type)); methodGenerator.Emit(OpCodes.Stloc_S, isReturnLocalBuilder); #endregion methodGenerator.Emit(OpCodes.Leave_S, returnLable); if (method.ReturnValueType != null) { methodGenerator.MarkLabel(returnTypeErrorLabel); #region return socket.SendOutput(@ReturnValue.Type); methodGenerator.Emit(OpCodes.Ldarg_1); methodGenerator.Emit(OpCodes.Ldloca_S, returnLocalBuilder); methodGenerator.Emit(OpCodes.Ldfld, returnTypeField); methodGenerator.call(Metadata.ServerSocketSendOutputReturnTypeMethod); methodGenerator.Emit(OpCodes.Stloc_S, isReturnLocalBuilder); #endregion } } } methodGenerator.Emit(OpCodes.Leave_S, returnLable); if (method.ParameterType != null) { methodGenerator.MarkLabel(serverDeSerializeErrorLabel); #region returnType = AutoCSer.Net.TcpServer.ReturnType.ServerDeSerializeError; methodGenerator.int32((byte)AutoCSer.Net.TcpServer.ReturnType.ServerDeSerializeError); methodGenerator.Emit(OpCodes.Stloc_S, returnTypeLocalBuilder); #endregion methodGenerator.Emit(OpCodes.Leave_S, pushLabel); } #region catch (Exception error) methodGenerator.BeginCatchBlock(typeof(Exception)); LocalBuilder errorLocalBuilder = methodGenerator.DeclareLocal(typeof(Exception)); methodGenerator.Emit(OpCodes.Stloc_S, errorLocalBuilder); #endregion #region returnType = AutoCSer.Net.TcpServer.ReturnType.ServerException; methodGenerator.int32((byte)AutoCSer.Net.TcpServer.ReturnType.ServerException); methodGenerator.Emit(OpCodes.Stloc_S, returnTypeLocalBuilder); #endregion #region socket.Log(error); methodGenerator.Emit(OpCodes.Ldarg_1); methodGenerator.Emit(OpCodes.Ldloc_S, errorLocalBuilder); methodGenerator.call(Metadata.ServerSocketLogMethod); #endregion methodGenerator.Emit(OpCodes.Leave_S, pushLabel); #region try end methodGenerator.EndExceptionBlock(); #endregion methodGenerator.MarkLabel(pushLabel); if (method.OutputParameterType == null) { #region return socket.Send(returnType); methodGenerator.Emit(OpCodes.Ldarg_1); methodGenerator.Emit(OpCodes.Ldloc_S, returnTypeLocalBuilder); methodGenerator.call(Metadata.ServerSocketSendReturnTypeMethod); methodGenerator.Emit(OpCodes.Ret); #endregion } else { #region return socket.SendOutput(returnType); methodGenerator.Emit(OpCodes.Ldarg_1); methodGenerator.Emit(OpCodes.Ldloc_S, returnTypeLocalBuilder); methodGenerator.call(Metadata.ServerSocketSendOutputReturnTypeMethod); methodGenerator.Emit(OpCodes.Ret); #endregion } methodGenerator.MarkLabel(returnLable); methodGenerator.Emit(OpCodes.Ldloc_S, isReturnLocalBuilder); methodGenerator.Emit(OpCodes.Ret); } #region case @MethodIndex: return @MethodIndexName(socket, ref data); doCommandGenerator.MarkLabel(method.DoCommandLabel); doCommandGenerator.Emit(OpCodes.Ldarg_0); doCommandGenerator.Emit(OpCodes.Ldarg_2); doCommandGenerator.Emit(OpCodes.Ldarg_3); doCommandGenerator.call(methodBuilder); doCommandGenerator.Emit(OpCodes.Ret); #endregion method.DoCommandLabel = default(Label); } } doCommandGenerator.Emit(OpCodes.Ret); staticConstructorGenerator.Emit(OpCodes.Ret); return(typeBuilder.CreateType()); }
/// <summary> /// 为指定接口动态创建代理类型 /// </summary> /// <param name="interfaceType"></param> /// <returns></returns> private static Type DynamicallyCreateProxyType(Type interfaceType) { var methodInfo = MethodBase.GetCurrentMethod(); String methodName = methodInfo.Name; Type objectType = typeof(Object); String assemblyName = "DynamicAssembly"; String moudleName = "DynamicMoudle"; String typeName = interfaceType.FullName + ".DynamicProxy"; String field_handler_Name = "_handler"; String field_interfaceType_Name = "_interfaceType"; //在当前程序域中构建程序集信息 AppDomain domain = AppDomain.CurrentDomain; //构建一个程序集 AssemblyName assemblyNameObj = new AssemblyName(assemblyName); assemblyNameObj.Version = new Version(1, 0, 0, 0); assemblyNameObj.CultureInfo = null; #if NET40 AssemblyBuilder assemblyBuilder = domain.DefineDynamicAssembly( assemblyNameObj, AssemblyBuilderAccess.RunAndCollect); #else AssemblyBuilder assemblyBuilder = AssemblyBuilder.DefineDynamicAssembly( assemblyNameObj, AssemblyBuilderAccess.RunAndCollect); #endif //在程序集中构建基本模块 ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule(moudleName); //在模块中构建类型 TypeBuilder typeBuilder = moduleBuilder.DefineType( typeName, TypeAttributes.Class | TypeAttributes.Public | TypeAttributes.Sealed, objectType, new Type[] { interfaceType, typeof(IDisposable) }); //为类型构建字段成员 FieldBuilder handlerField = typeBuilder.DefineField( field_handler_Name, typeof(IInvokeHandler), FieldAttributes.Private); FieldBuilder interfaceTypeField = typeBuilder.DefineField( field_interfaceType_Name, interfaceType, FieldAttributes.Private); //为类型构建构造函数信息 ConstructorInfo objectConstructorInfo = objectType.GetConstructor(new Type[] { }); //public DynamicProxy(IDynamicProxyHandler handler,Type interfaceType) ConstructorBuilder constructorBuilder = typeBuilder.DefineConstructor( MethodAttributes.Public, CallingConventions.Standard, new Type[] { typeof(IInvokeHandler), typeof(Type) }); ILGenerator iLGenerator = constructorBuilder.GetILGenerator(); //在构造函数中使用参数为私有字赋值 //this._handler=handler; iLGenerator.Emit(OpCodes.Ldarg_0); iLGenerator.Emit(OpCodes.Ldarg_1); iLGenerator.Emit(OpCodes.Stfld, handlerField); //this._interfaceType=interfaceType; iLGenerator.Emit(OpCodes.Ldarg_0); iLGenerator.Emit(OpCodes.Ldarg_2); iLGenerator.Emit(OpCodes.Stfld, interfaceTypeField); //调用基类的构造函数 iLGenerator.Emit(OpCodes.Ldarg_0); iLGenerator.Emit(OpCodes.Call, objectConstructorInfo); iLGenerator.Emit(OpCodes.Ret); //为类型构建方法成员 DynamicallyCreateProxyTypeMethod(interfaceType, typeBuilder, handlerField, interfaceTypeField); DynamicallyCreateProxyTypeMethod(typeof(IDisposable), typeBuilder, handlerField, interfaceTypeField); #if NET40 return(typeBuilder.CreateType()); #else return(typeBuilder.CreateTypeInfo()); #endif }
public static Type BuildDynAssembly() { Type pointType = null; AppDomain currentDom = Thread.GetDomain(); Console.Write("Please enter a name for your new assembly: "); StringBuilder asmFileNameBldr = new StringBuilder(); asmFileNameBldr.Append(Console.ReadLine()); asmFileNameBldr.Append(".exe"); string asmFileName = asmFileNameBldr.ToString(); AssemblyName myAsmName = new AssemblyName(); myAsmName.Name = "MyDynamicAssembly"; AssemblyBuilder myAsmBldr = currentDom.DefineDynamicAssembly( myAsmName, AssemblyBuilderAccess.RunAndSave); // We've created a dynamic assembly space - now, we need to create a module // within it to reflect the type Point into. ModuleBuilder myModuleBldr = myAsmBldr.DefineDynamicModule(asmFileName, asmFileName); TypeBuilder myTypeBldr = myModuleBldr.DefineType("Point"); FieldBuilder xField = myTypeBldr.DefineField("x", typeof(int), FieldAttributes.Private); FieldBuilder yField = myTypeBldr.DefineField("y", typeof(int), FieldAttributes.Private); // Build the constructor. Type objType = Type.GetType("System.Object"); ConstructorInfo objCtor = objType.GetConstructor(new Type[0]); Type[] ctorParams = new Type[] { typeof(int), typeof(int) }; ConstructorBuilder pointCtor = myTypeBldr.DefineConstructor( MethodAttributes.Public, CallingConventions.Standard, ctorParams); ILGenerator ctorIL = pointCtor.GetILGenerator(); ctorIL.Emit(OpCodes.Ldarg_0); ctorIL.Emit(OpCodes.Call, objCtor); ctorIL.Emit(OpCodes.Ldarg_0); ctorIL.Emit(OpCodes.Ldarg_1); ctorIL.Emit(OpCodes.Stfld, xField); ctorIL.Emit(OpCodes.Ldarg_0); ctorIL.Emit(OpCodes.Ldarg_2); ctorIL.Emit(OpCodes.Stfld, yField); ctorIL.Emit(OpCodes.Ret); // Build the DotProduct method. Console.WriteLine("Constructor built."); MethodBuilder pointDPBldr = myTypeBldr.DefineMethod("DotProduct", MethodAttributes.Public, typeof(int), new Type[] { myTypeBldr }); ILGenerator dpIL = pointDPBldr.GetILGenerator(); dpIL.Emit(OpCodes.Ldarg_0); dpIL.Emit(OpCodes.Ldfld, xField); dpIL.Emit(OpCodes.Ldarg_1); dpIL.Emit(OpCodes.Ldfld, xField); dpIL.Emit(OpCodes.Mul_Ovf_Un); dpIL.Emit(OpCodes.Ldarg_0); dpIL.Emit(OpCodes.Ldfld, yField); dpIL.Emit(OpCodes.Ldarg_1); dpIL.Emit(OpCodes.Ldfld, yField); dpIL.Emit(OpCodes.Mul_Ovf_Un); dpIL.Emit(OpCodes.Add_Ovf_Un); dpIL.Emit(OpCodes.Ret); // Build the PointMain method. Console.WriteLine("DotProduct built."); MethodBuilder pointMainBldr = myTypeBldr.DefineMethod("PointMain", MethodAttributes.Public | MethodAttributes.Static, typeof(void), null); pointMainBldr.InitLocals = true; ILGenerator pmIL = pointMainBldr.GetILGenerator(); // We have four methods that we wish to call, and must represent as // MethodInfo tokens: // - void Console.WriteLine(string) // - string Console.ReadLine() // - int Convert.Int32(string) // - void Console.WriteLine(string, object[]) MethodInfo writeMI = typeof(Console).GetMethod( "Write", new Type[] { typeof(string) }); MethodInfo readLineMI = typeof(Console).GetMethod( "ReadLine", new Type[0]); MethodInfo convertInt32MI = typeof(Convert).GetMethod( "ToInt32", new Type[] { typeof(string) }); Type[] wlParams = new Type[] { typeof(string), typeof(object[]) }; MethodInfo writeLineMI = typeof(Console).GetMethod( "WriteLine", wlParams); // Although we could just refer to the local variables by // index (short ints for Ldloc/Stloc, bytes for LdLoc_S/Stloc_S), // this time, we'll use LocalBuilders for clarity and to // demonstrate their usage and syntax. LocalBuilder x1LB = pmIL.DeclareLocal(typeof(int)); LocalBuilder y1LB = pmIL.DeclareLocal(typeof(int)); LocalBuilder x2LB = pmIL.DeclareLocal(typeof(int)); LocalBuilder y2LB = pmIL.DeclareLocal(typeof(int)); LocalBuilder point1LB = pmIL.DeclareLocal(myTypeBldr); LocalBuilder point2LB = pmIL.DeclareLocal(myTypeBldr); LocalBuilder tempObjArrLB = pmIL.DeclareLocal(typeof(object[])); pmIL.Emit(OpCodes.Ldstr, "Enter the 'x' value for point 1: "); pmIL.EmitCall(OpCodes.Call, writeMI, null); pmIL.EmitCall(OpCodes.Call, readLineMI, null); pmIL.EmitCall(OpCodes.Call, convertInt32MI, null); pmIL.Emit(OpCodes.Stloc, x1LB); pmIL.Emit(OpCodes.Ldstr, "Enter the 'y' value for point 1: "); pmIL.EmitCall(OpCodes.Call, writeMI, null); pmIL.EmitCall(OpCodes.Call, readLineMI, null); pmIL.EmitCall(OpCodes.Call, convertInt32MI, null); pmIL.Emit(OpCodes.Stloc, y1LB); pmIL.Emit(OpCodes.Ldstr, "Enter the 'x' value for point 2: "); pmIL.EmitCall(OpCodes.Call, writeMI, null); pmIL.EmitCall(OpCodes.Call, readLineMI, null); pmIL.EmitCall(OpCodes.Call, convertInt32MI, null); pmIL.Emit(OpCodes.Stloc, x2LB); pmIL.Emit(OpCodes.Ldstr, "Enter the 'y' value for point 2: "); pmIL.EmitCall(OpCodes.Call, writeMI, null); pmIL.EmitCall(OpCodes.Call, readLineMI, null); pmIL.EmitCall(OpCodes.Call, convertInt32MI, null); pmIL.Emit(OpCodes.Stloc, y2LB); pmIL.Emit(OpCodes.Ldloc, x1LB); pmIL.Emit(OpCodes.Ldloc, y1LB); pmIL.Emit(OpCodes.Newobj, pointCtor); pmIL.Emit(OpCodes.Stloc, point1LB); pmIL.Emit(OpCodes.Ldloc, x2LB); pmIL.Emit(OpCodes.Ldloc, y2LB); pmIL.Emit(OpCodes.Newobj, pointCtor); pmIL.Emit(OpCodes.Stloc, point2LB); pmIL.Emit(OpCodes.Ldstr, "({0}, {1}) . ({2}, {3}) = {4}."); pmIL.Emit(OpCodes.Ldc_I4_5); pmIL.Emit(OpCodes.Newarr, typeof(Object)); pmIL.Emit(OpCodes.Stloc, tempObjArrLB); pmIL.Emit(OpCodes.Ldloc, tempObjArrLB); pmIL.Emit(OpCodes.Ldc_I4_0); pmIL.Emit(OpCodes.Ldloc, x1LB); pmIL.Emit(OpCodes.Box, typeof(int)); pmIL.Emit(OpCodes.Stelem_Ref); pmIL.Emit(OpCodes.Ldloc, tempObjArrLB); pmIL.Emit(OpCodes.Ldc_I4_1); pmIL.Emit(OpCodes.Ldloc, y1LB); pmIL.Emit(OpCodes.Box, typeof(int)); pmIL.Emit(OpCodes.Stelem_Ref); pmIL.Emit(OpCodes.Ldloc, tempObjArrLB); pmIL.Emit(OpCodes.Ldc_I4_2); pmIL.Emit(OpCodes.Ldloc, x2LB); pmIL.Emit(OpCodes.Box, typeof(int)); pmIL.Emit(OpCodes.Stelem_Ref); pmIL.Emit(OpCodes.Ldloc, tempObjArrLB); pmIL.Emit(OpCodes.Ldc_I4_3); pmIL.Emit(OpCodes.Ldloc, y2LB); pmIL.Emit(OpCodes.Box, typeof(int)); pmIL.Emit(OpCodes.Stelem_Ref); pmIL.Emit(OpCodes.Ldloc, tempObjArrLB); pmIL.Emit(OpCodes.Ldc_I4_4); pmIL.Emit(OpCodes.Ldloc, point1LB); pmIL.Emit(OpCodes.Ldloc, point2LB); pmIL.EmitCall(OpCodes.Callvirt, pointDPBldr, null); pmIL.Emit(OpCodes.Box, typeof(int)); pmIL.Emit(OpCodes.Stelem_Ref); pmIL.Emit(OpCodes.Ldloc, tempObjArrLB); pmIL.EmitCall(OpCodes.Call, writeLineMI, null); pmIL.Emit(OpCodes.Ret); Console.WriteLine("PointMain (entry point) built."); pointType = myTypeBldr.CreateType(); Console.WriteLine("Type completed."); myAsmBldr.SetEntryPoint(pointMainBldr); myAsmBldr.Save(asmFileName); Console.WriteLine("Assembly saved as '{0}'.", asmFileName); Console.WriteLine("Type '{0}' at the prompt to run your new " + "dynamically generated dot product calculator.", asmFileName); // After execution, this program will have generated and written to disk, // in the directory you executed it from, a program named // <name_you_entered_here>.exe. You can run it by typing // the name you gave it during execution, in the same directory where // you executed this program. return(pointType); }
public InterfaceImplementor(Handler handler) { Type intf = typeof(TInterface); string intname = intf.Name; if (!intf.IsInterface) { throw new ArgumentException("TInterface is not an interface"); } AssemblyName asmName = new AssemblyName(); asmName.Name = intname + "Implementation"; AppDomain ad = AppDomain.CurrentDomain; AssemblyBuilder ab = ad.DefineDynamicAssembly(asmName, AssemblyBuilderAccess.RunAndSave); ModuleBuilder mb = ab.DefineDynamicModule(asmName.Name, asmName.Name + ".dll"); TypeBuilder tb = mb.DefineType( asmName.Name + "Impl", TypeAttributes.Class, typeof(MarshalByRefObject), new Type[] { intf }); FieldBuilder methodHandler = tb.DefineField( "handler", typeof(Handler), FieldAttributes.Private); ConstructorInfo baseConstructorInfo = typeof(object).GetConstructor(new Type[0]); ConstructorBuilder cb = tb.DefineConstructor( MethodAttributes.Public, CallingConventions.Standard, new Type[] { typeof(Handler) }); // Make the constructor ILGenerator gen = cb.GetILGenerator(); gen.Emit(OpCodes.Ldarg_0); gen.Emit(OpCodes.Call, baseConstructorInfo); gen.Emit(OpCodes.Ldarg_0); gen.Emit(OpCodes.Ldarg_1); gen.Emit(OpCodes.Stfld, methodHandler); gen.Emit(OpCodes.Ret); foreach (MethodInfo mi in intf.GetMethods()) { ParameterInfo[] pis = mi.GetParameters(); MethodBuilder method = tb.DefineMethod( mi.Name, MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.Final | MethodAttributes.HideBySig | MethodAttributes.NewSlot, CallingConventions.Standard, mi.ReturnType, ArrayUtils.ConvertAll(pis, x => x.ParameterType)); ILGenerator mgen = method.GetILGenerator(); LocalBuilder lb = mgen.DeclareLocal(typeof(object[])); mgen.Emit(OpCodes.Nop); mgen.Emit(OpCodes.Ldarg_0); mgen.Emit(OpCodes.Ldfld, methodHandler); mgen.Emit(OpCodes.Ldstr, mi.Name); // Make the object array if (pis.Length == 0) { mgen.Emit(OpCodes.Ldc_I4_0); } else if (pis.Length == 1) { mgen.Emit(OpCodes.Ldc_I4_1); } else if (pis.Length == 2) { mgen.Emit(OpCodes.Ldc_I4_2); } else if (pis.Length == 3) { mgen.Emit(OpCodes.Ldc_I4_3); } else if (pis.Length == 4) { mgen.Emit(OpCodes.Ldc_I4_4); } else if (pis.Length == 5) { mgen.Emit(OpCodes.Ldc_I4_5); } else if (pis.Length == 6) { mgen.Emit(OpCodes.Ldc_I4_6); } else if (pis.Length == 7) { mgen.Emit(OpCodes.Ldc_I4_7); } else if (pis.Length == 8) { mgen.Emit(OpCodes.Ldc_I4_8); } else { mgen.Emit(OpCodes.Ldc_I4, pis.Length); } mgen.Emit(OpCodes.Newarr, typeof(object)); mgen.Emit(OpCodes.Stloc_0); for (int i = 0; i < pis.Length; i++) { // Load the object array mgen.Emit(OpCodes.Ldloc_0); if (i == 0) { mgen.Emit(OpCodes.Ldc_I4_0); mgen.Emit(OpCodes.Ldarg_1); } else { mgen.Emit(OpCodes.Ldc_I4, i); mgen.Emit(OpCodes.Ldarg, i + 1); } if (pis[i].ParameterType.IsValueType) { mgen.Emit(OpCodes.Box, pis[i].ParameterType); } mgen.Emit(OpCodes.Stelem_Ref); } mgen.Emit(OpCodes.Ldloc_0); mgen.EmitCall( OpCodes.Callvirt, typeof(Handler).GetMethod("Invoke"), new Type[] { typeof(object) }); if (mi.ReturnType == typeof(void)) { mgen.Emit(OpCodes.Pop); } mgen.Emit(OpCodes.Ret); tb.DefineMethodOverride(method, mi); } Type t = tb.CreateType(); ab.Save(asmName.Name + ".dll"); Interface = (TInterface)Activator.CreateInstance(t, handler); }
/* * Generates an implementation of klass, if it is an interface, or * a subclass of klass that delegates its virtual methods to a Lua table. */ public void GenerateClass(Type klass, out Type newType, out Type[][] returnTypes) { string typeName; lock (this) { typeName = "LuaGeneratedClass" + luaClassNumber; luaClassNumber++; } TypeBuilder myType; // Define a public class in the assembly, called typeName if (klass.IsInterface) { myType = newModule.DefineType(typeName, TypeAttributes.Public, typeof(object), new Type[] { klass, typeof(ILuaGeneratedType) }); } else { myType = newModule.DefineType(typeName, TypeAttributes.Public, klass, new Type[] { typeof(ILuaGeneratedType) }); } // Field that stores the Lua table FieldBuilder luaTableField = myType.DefineField("__luaInterface_luaTable", typeof(LuaTable), FieldAttributes.Public); // Field that stores the return types array FieldBuilder returnTypesField = myType.DefineField("__luaInterface_returnTypes", typeof(Type[][]), FieldAttributes.Public); // Generates the constructor for the new type, it takes a Lua table and an array // of return types and stores them in the respective fields ConstructorBuilder constructor = myType.DefineConstructor(MethodAttributes.Public, CallingConventions.Standard, new Type[] { typeof(LuaTable), typeof(Type[][]) }); ILGenerator generator = constructor.GetILGenerator(); generator.Emit(OpCodes.Ldarg_0); if (klass.IsInterface) { generator.Emit(OpCodes.Call, typeof(object).GetConstructor(Type.EmptyTypes)); } else { generator.Emit(OpCodes.Call, klass.GetConstructor(Type.EmptyTypes)); } generator.Emit(OpCodes.Ldarg_0); generator.Emit(OpCodes.Ldarg_1); generator.Emit(OpCodes.Stfld, luaTableField); generator.Emit(OpCodes.Ldarg_0); generator.Emit(OpCodes.Ldarg_2); generator.Emit(OpCodes.Stfld, returnTypesField); generator.Emit(OpCodes.Ret); // Generates overriden versions of the klass' public virtual methods MethodInfo[] classMethods = klass.GetMethods(); returnTypes = new Type[classMethods.Length][]; int i = 0; foreach (MethodInfo method in classMethods) { if (klass.IsInterface) { GenerateMethod(myType, method, MethodAttributes.HideBySig | MethodAttributes.Virtual | MethodAttributes.NewSlot, i, luaTableField, returnTypesField, false, out returnTypes[i]); i++; } else { if (!method.IsPrivate && !method.IsFinal && method.IsVirtual) { GenerateMethod(myType, method, (method.Attributes | MethodAttributes.NewSlot) ^ MethodAttributes.NewSlot, i, luaTableField, returnTypesField, true, out returnTypes[i]); i++; } } } // Generates an implementation of the __luaInterface_getLuaTable method MethodBuilder returnTableMethod = myType.DefineMethod("__luaInterface_getLuaTable", MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.Virtual, typeof(LuaTable), new Type[0]); myType.DefineMethodOverride(returnTableMethod, typeof(ILuaGeneratedType).GetMethod("__luaInterface_getLuaTable")); generator = returnTableMethod.GetILGenerator(); generator.Emit(OpCodes.Ldfld, luaTableField); generator.Emit(OpCodes.Ret); // Creates the type newType = myType.CreateType(); }
public static IComparer <T> Compile <T>(AssemblyEmitter assembly, Type objectType, Property[] props) { TypeBuilder typeBuilder = assembly.DefineType( "__distinct", TypeAttributes.Public, typeof(object) ); #region Constructor { ConstructorBuilder ctor = typeBuilder.DefineConstructor( MethodAttributes.Public, CallingConventions.Standard, Type.EmptyTypes ); ILGenerator il = ctor.GetILGenerator(); // : base() il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Call, typeof(T).GetConstructor(Type.EmptyTypes) ?? throw new Exception($"Could not find empty constructor for type {typeof(T).FullName}")); // return; il.Emit(OpCodes.Ret); } #endregion #region IComparer typeBuilder.AddInterfaceImplementation(typeof(IComparer <T>)); MethodBuilder compareMethod; #region Compare { MethodEmitter emitter = new MethodEmitter(typeBuilder); emitter.Define( /* name */ "Compare", /* attr */ MethodAttributes.Public | MethodAttributes.Virtual, /* return */ typeof(int), /* params */ new[] { typeof(T), typeof(T) }); LocalBuilder a = emitter.CreateLocal(objectType); LocalBuilder b = emitter.CreateLocal(objectType); LocalBuilder v = emitter.CreateLocal(typeof(int)); emitter.LoadArgument(1); emitter.CastAs(objectType); emitter.StoreLocal(a); emitter.LoadArgument(2); emitter.CastAs(objectType); emitter.StoreLocal(b); emitter.Load(0); emitter.StoreLocal(v); Label end = emitter.CreateLabel(); for (int i = 0; i < props.Length; ++i) { if (i > 0) { emitter.LoadLocal(v); emitter.BranchIfTrue(end); // if ( v != 0 ) return v; } Property prop = props[i]; emitter.LoadLocal(a); emitter.Chain(prop); bool couldCompare = emitter.CompareTo(1, delegate { emitter.LoadLocal(b); emitter.Chain(prop); }); if (!couldCompare) { throw new InvalidOperationException("Property is not comparable."); } emitter.StoreLocal(v); } emitter.MarkLabel(end); emitter.LoadLocal(v); emitter.Return(); typeBuilder.DefineMethodOverride( emitter.Method, typeof(IComparer <T>).GetMethod( "Compare", new[] { typeof(T), typeof(T) } ) ?? throw new Exception($"No Compare method found for type {typeof(T).FullName}") ); compareMethod = emitter.Method; } #endregion #endregion #region IEqualityComparer typeBuilder.AddInterfaceImplementation(typeof(IEqualityComparer <T>)); #region Equals { MethodEmitter emitter = new MethodEmitter(typeBuilder); emitter.Define( /* name */ "Equals", /* attr */ MethodAttributes.Public | MethodAttributes.Virtual, /* return */ typeof(bool), /* params */ new[] { typeof(T), typeof(T) }); emitter.Generator.Emit(OpCodes.Ldarg_0); emitter.Generator.Emit(OpCodes.Ldarg_1); emitter.Generator.Emit(OpCodes.Ldarg_2); emitter.Generator.Emit(OpCodes.Call, compareMethod); emitter.Generator.Emit(OpCodes.Ldc_I4_0); emitter.Generator.Emit(OpCodes.Ceq); emitter.Generator.Emit(OpCodes.Ret); typeBuilder.DefineMethodOverride( emitter.Method, typeof(IEqualityComparer <T>).GetMethod( "Equals", new[] { typeof(T), typeof(T) } ) ?? throw new Exception($"No Equals method found for type {typeof(T).FullName}") ); } #endregion #region GetHashCode { MethodEmitter emitter = new MethodEmitter(typeBuilder); emitter.Define( /* name */ "GetHashCode", /* attr */ MethodAttributes.Public | MethodAttributes.Virtual, /* return */ typeof(int), /* params */ new[] { typeof(T) }); LocalBuilder obj = emitter.CreateLocal(objectType); emitter.LoadArgument(1); emitter.CastAs(objectType); emitter.StoreLocal(obj); for (int i = 0; i < props.Length; ++i) { Property prop = props[i]; emitter.LoadLocal(obj); emitter.Chain(prop); Type active = emitter.Active; MethodInfo getHashCode = active.GetMethod("GetHashCode", Type.EmptyTypes); getHashCode ??= typeof(T).GetMethod("GetHashCode", Type.EmptyTypes); if (active != typeof(int)) { if (!active.IsValueType) { LocalBuilder value = emitter.AcquireTemp(active); Label valueNotNull = emitter.CreateLabel(); Label done = emitter.CreateLabel(); emitter.StoreLocal(value); emitter.LoadLocal(value); emitter.BranchIfTrue(valueNotNull); emitter.Load(0); emitter.Pop(typeof(int)); emitter.Branch(done); emitter.MarkLabel(valueNotNull); emitter.LoadLocal(value); emitter.Call(getHashCode); emitter.ReleaseTemp(value); emitter.MarkLabel(done); } else { emitter.Call(getHashCode); } } if (i > 0) { emitter.Xor(); } } emitter.Return(); typeBuilder.DefineMethodOverride( emitter.Method, typeof(IEqualityComparer <T>).GetMethod( "GetHashCode", new[] { typeof(T) } ) ?? throw new Exception($"No GetHashCode method found for type {typeof(T).FullName}") ); } #endregion #endregion Type comparerType = typeBuilder.CreateType(); return((IComparer <T>)ActivatorUtil.CreateInstance(comparerType)); }
private Type CreateType(IProxyInvocationHandler handler, Type[] interfaces, string dynamicTypeName) { Type retVal = null; if (handler != null && interfaces != null) { Type objType = typeof(System.Object); Type handlerType = typeof(IProxyInvocationHandler); AppDomain domain = Thread.GetDomain(); AssemblyName assemblyName = new AssemblyName(); assemblyName.Name = ASSEMBLY_NAME; assemblyName.Version = new Version(1, 0, 0, 0); // create a new assembly for this proxy, one that isn't presisted on the file system AssemblyBuilder assemblyBuilder = domain.DefineDynamicAssembly( assemblyName, AssemblyBuilderAccess.Run); // assemblyName, AssemblyBuilderAccess.RunAndSave,"."); // to save it to the disk // create a new module for this proxy ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule(MODULE_NAME); // Set the class to be public and sealed TypeAttributes typeAttributes = TypeAttributes.Class | TypeAttributes.Public | TypeAttributes.Sealed; // Gather up the proxy information and create a new type builder. One that // inherits from Object and implements the interface passed in TypeBuilder typeBuilder = moduleBuilder.DefineType( dynamicTypeName, typeAttributes, objType, interfaces); // Define a member variable to hold the delegate FieldBuilder handlerField = typeBuilder.DefineField( HANDLER_NAME, handlerType, FieldAttributes.Private); // build a constructor that takes the delegate object as the only argument //ConstructorInfo defaultObjConstructor = objType.GetConstructor( new Type[0] ); ConstructorInfo superConstructor = objType.GetConstructor(new Type[0]); ConstructorBuilder delegateConstructor = typeBuilder.DefineConstructor( MethodAttributes.Public, CallingConventions.Standard, new Type[] { handlerType }); #region ( "Constructor IL Code" ) ILGenerator constructorIL = delegateConstructor.GetILGenerator(); // Load "this" constructorIL.Emit(OpCodes.Ldarg_0); // Load first constructor parameter constructorIL.Emit(OpCodes.Ldarg_1); // Set the first parameter into the handler field constructorIL.Emit(OpCodes.Stfld, handlerField); // Load "this" constructorIL.Emit(OpCodes.Ldarg_0); // Call the super constructor constructorIL.Emit(OpCodes.Call, superConstructor); // Constructor return constructorIL.Emit(OpCodes.Ret); #endregion // for every method that the interfaces define, build a corresponding // method in the dynamic type that calls the handlers invoke method. foreach (Type interfaceType in interfaces) { GenerateMethod(interfaceType, handlerField, typeBuilder); } retVal = typeBuilder.CreateType(); // assemblyBuilder.Save(dynamicTypeName + ".dll"); } return(retVal); }
private void DefineConstructors() { BindingFlags bindingFlags = BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance; ConstructorInfo emptyCtor = _tb.BaseType.GetConstructor(bindingFlags, null, Type.EmptyTypes, null); ConstructorInfo classArgCtor = null; bool deserializerFound = false; foreach (var baseCtor in _tb.BaseType.GetConstructors(bindingFlags)) { if (!baseCtor.IsPublic && !baseCtor.IsFamily) { continue; } int oldLength = baseCtor.GetParameters().Length; List <Type> newParams = new List <Type>(oldLength + 1); foreach (var param in baseCtor.GetParameters()) { newParams.Add(param.ParameterType); } int offset = 1; bool isDeserializer = false; if (oldLength > 0 && newParams[0] == typeof(RubyClass)) { // Build a simple pass-through constructor offset = 0; #if !SILVERLIGHT } else if (oldLength == 2 && newParams[0] == typeof(SerializationInfo) && newParams[1] == typeof(StreamingContext)) { // Build a deserializer deserializerFound = true; isDeserializer = true; offset = 0; #endif } else { // Special-case for Exception if (_tb.IsSubclassOf(typeof(Exception)) && IsAvailable(emptyCtor)) { if (oldLength == 0) { // Skip this constructor; it would conflict with the one we're going to build next continue; } else if (oldLength == 1 && newParams[0] == typeof(string)) { // Special case exceptions to improve interop. Ruby's default message for an exception is the name of the exception class. BuildExceptionConstructor(baseCtor); } } // Add RubyClass to the head of the parameter list newParams.Insert(0, typeof(RubyClass)); } // Build a new constructor based on this base class ctor ConstructorBuilder cb = _tb.DefineConstructor(MethodAttributes.Public, CallingConventions.Standard, newParams.ToArray()); ILGen il = new ILGen(cb.GetILGenerator()); il.EmitLoadArg(0); for (int i = 1; i < newParams.Count; i++) { il.EmitLoadArg(i + offset); } il.Emit(OpCodes.Call, baseCtor); if (!isDeserializer) { // ctor(RubyClass! class, ...) : ... { this._class = class; } il.EmitLoadArg(0); il.EmitLoadArg(1); il.EmitFieldSet(_classField); } else { // ctor(SerializationInfo! info, StreamingContext! context) : base { // RubyOps.DeserializeObject(out this._instanceData, out this._class, info); // } il.EmitLoadArg(0); il.EmitFieldAddress(_instanceDataField); il.EmitLoadArg(0); il.EmitFieldAddress(_classField); il.EmitLoadArg(1); il.EmitCall(typeof(RubyOps).GetMethod("DeserializeObject")); } il.Emit(OpCodes.Ret); if (oldLength == 0) { classArgCtor = cb; } } #if !SILVERLIGHT if (classArgCtor != null && !deserializerFound) { // We didn't previously find a deserialization constructor. If we can, build one now. BuildDeserializationConstructor(classArgCtor); } #endif }
private static Type CreateRowType(IDictionary <string, Type> properties) { string[] propertyNames = properties.Keys.ToArray(); Type[] propertyTypes = properties.Values.ToArray(); TypeBuilder typeBuilder; lock (moduleBuilderLock) { typeCount++; typeBuilder = moduleBuilder.DefineType( string.Format("DataRow{0}", typeCount), TypeAttributes.Public, // Derive from object typeof(DataRow), // No interfaces Type.EmptyTypes); } bool isLarge = LargeDataRowAttribute.LargePropertyCount <= properties.Count; #region LargeDataRowAttribute if (isLarge) { ConstructorInfo largeDataRowAttrCtor = typeof(LargeDataRowAttribute).GetConstructor( BindingFlags.Instance | BindingFlags.Public, null, Type.EmptyTypes, null); typeBuilder.SetCustomAttribute( new CustomAttributeBuilder(largeDataRowAttrCtor, new object[0])); } #endregion #region Properties and fields FieldBuilder[] fields = new FieldBuilder[properties.Count]; for (int i = 0; i < properties.Count; i++) { string name = propertyNames[i]; Type type = propertyTypes[i]; FieldBuilder field = CreateFieldAndProperty(typeBuilder, name, i, type); fields[i] = field; } #endregion #region Constructor ConstructorBuilder ctorBuilder = typeBuilder.DefineConstructor( MethodAttributes.Public, CallingConventions.Standard, isLarge ? new Type[] { typeof(object[]) } : propertyTypes); if (isLarge) { ctorBuilder.DefineParameter(0, ParameterAttributes.None, "args"); } else { for (int i = 0; i < propertyNames.Length; i++) { ctorBuilder.DefineParameter( i, ParameterAttributes.None, propertyNames[i]); } } GenerateConstructorIL(ctorBuilder.GetILGenerator(), fields, isLarge); #endregion #region GetHashCode MethodBuilder getHashCodeBuilder = typeBuilder.DefineMethod( "GetHashCode", MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.HideBySig, null, Type.EmptyTypes); getHashCodeBuilder.SetReturnType(typeof(int)); GenerateGetHashcodeIL(getHashCodeBuilder.GetILGenerator(), fields); #endregion #region Equals MethodBuilder equalsBuilder = typeBuilder.DefineMethod( "Equals", MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.HideBySig, null, Type.EmptyTypes); equalsBuilder.SetParameters(new Type[] { typeof(object) }); equalsBuilder.SetReturnType(typeof(bool)); GenerateEqualsIL(equalsBuilder.GetILGenerator(), fields, typeBuilder); #endregion #region GetValue MethodBuilder getValueBuilder = typeBuilder.DefineMethod( GetValueNameMethod.Name, MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.HideBySig, null, Type.EmptyTypes); getValueBuilder.SetParameters(new Type[] { typeof(int) }); getValueBuilder.SetReturnType(typeof(object)); GenerateGetValueIL(getValueBuilder.GetILGenerator(), fields, typeBuilder); #endregion return(typeBuilder.CreateType()); }
public static T Import <T>(INativeLibImporter importer, string libName, string version, bool suppressUnload) where T : class { Console.WriteLine("Import: " + $"{libName}-{version}"); //var subdir = GetArchName(RuntimeInformation.ProcessArchitecture); var runtimeId = GetRuntimeId(RuntimeInformation.ProcessArchitecture); var assemblyName = new AssemblyName("DynamicLink"); var assemblyBuilder = CurrentFramework.DefineDynamicAssembly(assemblyName, System.Reflection.Emit.AssemblyBuilderAccess.Run); var moduleBuilder = assemblyBuilder.DefineDynamicModule("DynLinkModule"); string typeName = typeof(T).Name + "_impl"; var typeBuilder = moduleBuilder.DefineType(typeName, TypeAttributes.Public | TypeAttributes.Class | TypeAttributes.AutoClass | TypeAttributes.AnsiClass | TypeAttributes.BeforeFieldInit | TypeAttributes.AutoLayout, typeof(T)); FieldBuilder field_importer = typeBuilder.DefineField("importer", typeof(INativeLibImporter), FieldAttributes.Private | FieldAttributes.InitOnly); FieldBuilder field_libraryHandle = typeBuilder.DefineField("libraryHandle", typeof(IntPtr), FieldAttributes.Private | FieldAttributes.InitOnly); var methods = typeof(T).GetTypeInfo().GetMethods(BindingFlags.Public | BindingFlags.Instance).Where(m => m.IsAbstract && !m.IsGenericMethod).ToArray(); // Define delegate types for each of the method signatures var delegateMap = new Dictionary <string, Type>(); foreach (var method in methods) { var sig = GetMethodSig(method); if (delegateMap.ContainsKey(sig)) { continue; } var delegateTypeInfo = CreateDelegateType(moduleBuilder, method); delegateMap.Add(sig, delegateTypeInfo.AsType()); } // Define one field for each method to hold a delegate var delegates = methods.Select(m => new { MethodInfo = m, DelegateType = delegateMap[GetMethodSig(m)], }).ToArray(); var delegateFields = delegates.Select((d, i) => typeBuilder.DefineField($"{d.MethodInfo.Name}_func_{i}", d.DelegateType, FieldAttributes.Private)).ToArray(); // Create the constructor which will initialize the importer and library handle // and also use the importer to populate each of the delegate fields ConstructorBuilder constructor = typeBuilder.DefineConstructor(MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName, CallingConventions.Standard, new Type[] { typeof(INativeLibImporter), typeof(IntPtr) }); { var baseConstructor = typeof(T).GetTypeInfo().GetConstructors().Where(con => con.GetParameters().Length == 0).First(); ILGenerator il = constructor.GetILGenerator(); // Call base constructor il.Emit(OpCodes.Ldarg_0); // this il.Emit(OpCodes.Call, baseConstructor); // Store importer field il.Emit(OpCodes.Ldarg_0); // this il.Emit(OpCodes.Ldarg_1); // importer il.Emit(OpCodes.Stfld, field_importer); // Load and store library handle il.Emit(OpCodes.Ldarg_0); // this il.Emit(OpCodes.Ldarg_2); // library handle il.Emit(OpCodes.Stfld, field_libraryHandle); var getDelegateMethod = typeof(INativeLibImporter).GetTypeInfo().GetMethod("GetDelegate"); // Initialize each delegate field for (int i = 0; i < delegateFields.Length; i++) { var delegateType = delegates[i].DelegateType; il.Emit(OpCodes.Ldarg_0); // this il.Emit(OpCodes.Ldarg_1); // importer il.Emit(OpCodes.Ldarg_0); // this il.Emit(OpCodes.Ldfld, field_libraryHandle); il.Emit(OpCodes.Ldstr, delegates[i].MethodInfo.Name); // use method name from original class as entry point il.Emit(OpCodes.Ldtoken, delegateType); // the delegate type il.Emit(OpCodes.Call, typeof(System.Type).GetTypeInfo().GetMethod("GetTypeFromHandle")); // typeof() il.Emit(OpCodes.Callvirt, getDelegateMethod); // importer.GetDelegate() il.Emit(OpCodes.Isinst, delegateType); // as <delegate type> il.Emit(OpCodes.Stfld, delegateFields[i]); } // End of constructor il.Emit(OpCodes.Ret); } // Create destructor var destructor = typeBuilder.DefineMethod("Finalize", MethodAttributes.Family | MethodAttributes.Virtual | MethodAttributes.HideBySig); { var baseDestructor = typeof(T).GetTypeInfo().GetMethod("Finalize", BindingFlags.NonPublic | BindingFlags.Instance); var il = destructor.GetILGenerator(); var end = il.DefineLabel(); il.BeginExceptionBlock(); if (!suppressUnload) { il.Emit(OpCodes.Ldarg_0); // this il.Emit(OpCodes.Ldfld, field_importer); // .importer il.Emit(OpCodes.Ldarg_0); // this il.Emit(OpCodes.Ldfld, field_libraryHandle); // .libraryHandle il.Emit(OpCodes.Callvirt, typeof(INativeLibImporter).GetTypeInfo().GetMethod("FreeLibrary")); // INativeLibImporter::FreeLibrary() } //il.Emit(OpCodes.Leave, end); il.BeginFinallyBlock(); il.Emit(OpCodes.Ldarg_0); // this il.Emit(OpCodes.Call, baseDestructor); // object::Finalize() //il.Emit(OpCodes.Endfinally); il.EndExceptionBlock(); il.MarkLabel(end); il.Emit(OpCodes.Ret); } var nativeFunctionMissingExceptionConstructor = typeof(NativeFunctionMissingException).GetTypeInfo().GetConstructor(new[] { typeof(string) }); // Now override each method from the base class for (int i = 0; i < delegateFields.Length; i++) { var baseMethod = delegates[i].MethodInfo; var args = baseMethod.GetParameters(); var omethod = typeBuilder.DefineMethod( baseMethod.Name, (baseMethod.Attributes & ~(MethodAttributes.Abstract | MethodAttributes.NewSlot)) | MethodAttributes.Virtual, baseMethod.CallingConvention, baseMethod.ReturnType, args.Select(arg => arg.ParameterType).ToArray() ); var il = omethod.GetILGenerator(); il.Emit(OpCodes.Ldarg_0); // this il.Emit(OpCodes.Ldfld, delegateFields[i]); // {field} il.Emit(OpCodes.Dup); var error = il.DefineLabel(); il.Emit(OpCodes.Brfalse_S, error); if (args.Length >= 1) { il.Emit(OpCodes.Ldarg_1); } if (args.Length >= 2) { il.Emit(OpCodes.Ldarg_2); } if (args.Length >= 3) { il.Emit(OpCodes.Ldarg_3); } for (short argNum = 4; argNum <= args.Length; argNum++) { il.Emit(OpCodes.Ldarg_S, argNum); } il.Emit(OpCodes.Tailcall); il.Emit(OpCodes.Callvirt, delegates[i].DelegateType.GetTypeInfo().GetMethod("Invoke")); il.Emit(OpCodes.Ret); il.MarkLabel(error); il.Emit(OpCodes.Ldstr, baseMethod.ToString()); il.Emit(OpCodes.Newobj, nativeFunctionMissingExceptionConstructor); il.Emit(OpCodes.Throw); } var type = typeBuilder.CreateTypeInfo(); var versionParts = version.Split('.'); //var names = versionParts.Select((p, i) => libName + "-" + string.Join(".", versionParts.Take(i + 1))) // .Reverse() // .Concat(Enumerable.Repeat(libName, 1)); // Skip looking for versions, only lib with static name. var names = new[] { libName }; // try to load locally var paths = new[] { Path.Combine("runtimes", runtimeId, "native"), //Path.Combine("native", subdir), //"native", //subdir, "", }; Console.WriteLine("paths: " + string.Join(':', paths)); var basePaths = new string[] { Directory.GetCurrentDirectory(), Path.GetDirectoryName(UriToPath(AppContext.BaseDirectory)), // Path.GetDirectoryName(UriToPath(Transitional.CurrentFramework.GetBaseDirectory())), Path.GetDirectoryName(Assembly.GetEntryAssembly()?.Location), // Path.GetDirectoryName(typeof(PosixImporter).GetTypeInfo().Assembly.Location), }; Console.WriteLine("basePaths: " + string.Join(':', basePaths)); var search = basePaths .Where(p => p != null) .Distinct() .SelectMany(basePath => paths.SelectMany(path => names.Select(n => Path.Combine(basePath, path, importer.Translate(n)))) .Concat(names.Select(n => importer.Translate(n))) ) .Select(path => new SearchPath { Path = path }) .ToArray(); foreach (var spec in search) { var construct = type.GetConstructor(new Type[] { typeof(INativeLibImporter), typeof(IntPtr) }); IntPtr lib = IntPtr.Zero; try { Console.WriteLine("LoadLibrary: " + spec.Path); lib = importer.LoadLibrary(spec.Path); if (lib == IntPtr.Zero) { throw new NativeLoadException("LoadLibrary returned 0", null); } } catch (TargetInvocationException tie) { spec.Error = tie.InnerException; Console.WriteLine("TargetInvocationException: " + spec.Error.Message); continue; } catch (Exception e) { spec.Error = e; Console.WriteLine("Exception: " + spec.Error.Message); continue; } var obj = construct.Invoke(new object[] { importer, lib }); var t = obj as T; return(t); } throw new NativeLoadException("Unable to locate rocksdb native library, either install it, or use RocksDbNative nuget package\nSearched:\n" + string.Join("\n", search.Select(s => $"{s.Path}: ({s.Error.GetType().Name}) {s.Error.Message}")), null); }
/// <summary> /// Compiles the functions. /// </summary> /// <remarks><pre> /// 20 Dec 2005 - Jeremy Roberts /// </pre></remarks> protected void compile() { // Code to set up the object. // Create a new AppDomain. // Set up assembly. // //NewAppDomain = System.AppDomain.CreateDomain("NewApplicationDomain"); //NewAppDomain = appDomain; AssemblyName assemblyName = new AssemblyName(); assemblyName.Name = "EmittedAssembly"; AssemblyBuilder assembly = Thread.GetDomain().DefineDynamicAssembly( //AssemblyBuilder assembly = NewAppDomain.DefineDynamicAssembly( assemblyName, //AssemblyBuilderAccess.Save); AssemblyBuilderAccess.Run); //AssemblyBuilderAccess.RunAndSave); // Add Dynamic Module // ModuleBuilder module; module = assembly.DefineDynamicModule("EmittedModule"); TypeBuilder dynamicFunctionClass = module.DefineType( "DynamicFunction", TypeAttributes.Public, typeof(DynamicFunction)); // Define class constructor // Type objType = Type.GetType("System.Object"); ConstructorInfo objConstructor = objType.GetConstructor(new Type[0]); Type[] constructorParams = { }; ConstructorBuilder constructor = dynamicFunctionClass.DefineConstructor( MethodAttributes.Public, CallingConventions.Standard, constructorParams); // Emit the class constructor. // ILGenerator constructorIL = constructor.GetILGenerator(); constructorIL.Emit(OpCodes.Ldarg_0); constructorIL.Emit(OpCodes.Call, objConstructor); constructorIL.Emit(OpCodes.Ret); // Define "EvaluateD" function. // Type[] args = { typeof(Dictionary <string, double>) }; MethodBuilder evalMethodD = dynamicFunctionClass.DefineMethod( "EvaluateD", MethodAttributes.Public | MethodAttributes.Virtual, typeof(double), args); ILGenerator methodILD; methodILD = evalMethodD.GetILGenerator(); emitFunction(this.PostFix, methodILD); // Define "EvaluateB" function. // MethodBuilder evalMethodB = dynamicFunctionClass.DefineMethod( "EvaluateB", MethodAttributes.Public | MethodAttributes.Virtual, typeof(bool), args); ILGenerator methodILB; methodILB = evalMethodB.GetILGenerator(); emitFunction(this.PostFix, methodILB); // Create an object to use. // Type dt = dynamicFunctionClass.CreateType(); //assembly.Save("assem.dll"); //assembly.Save("x.exe"); //return (function)Activator.CreateInstance(dt, new Object[] { }); this.dynamicFunction = (DynamicFunction)Activator.CreateInstance(dt, new Object[] { }); }
private static Type GetWrapperTypeNoCache(Type type, bool logHistory) { if (type.IsSealed) { throw new ArgumentException("The supplied type must not be sealed."); } AppDomain myDomain = AppDomain.CurrentDomain; AssemblyName myAsmName = new AssemblyName(type.Assembly.FullName.Remove(type.Assembly.FullName.IndexOf(",")) + ".__PropertyWatcher"); AssemblyBuilder myAssembly = myDomain.DefineDynamicAssembly(myAsmName, AssemblyBuilderAccess.RunAndSave); var module = myAssembly.DefineDynamicModule(myAsmName.Name, myAsmName.Name + ".dll"); TypeBuilder typeBuilder = module.DefineType(type.Name, TypeAttributes.Public, type); var propertyWatcherType = typeof(PropertyWatcher <>).MakeGenericType(type); var propertyWatcherField = typeBuilder.DefineField(FieldName, propertyWatcherType, FieldAttributes.Public | FieldAttributes.InitOnly); var propertyWatcherConstructor = propertyWatcherType.GetConstructor(new[] { typeof(bool) }); foreach (var oldConstructor in type.GetConstructors()) { Type[] paramTypes = oldConstructor.GetParameters().Select(c => c.ParameterType).ToArray(); ConstructorBuilder newConstructorMethodBuilder = typeBuilder.DefineConstructor(oldConstructor.Attributes, oldConstructor.CallingConvention, paramTypes); ILGenerator constructorIL = newConstructorMethodBuilder.GetILGenerator(); constructorIL.Emit(OpCodes.Ldarg_0); constructorIL.Emit(logHistory ? OpCodes.Ldc_I4_1 : OpCodes.Ldc_I4_0); constructorIL.Emit(OpCodes.Newobj, propertyWatcherConstructor); constructorIL.Emit(OpCodes.Stfld, propertyWatcherField); constructorIL.Emit(OpCodes.Ldarg_0); for (int v = 0; v < paramTypes.Length; v++) { constructorIL.Emit(OpCodes.Ldarga_S, v + 1); } constructorIL.Emit(OpCodes.Call, oldConstructor); constructorIL.Emit(OpCodes.Ret); } var setMethod = propertyWatcherType.GetMethod("Set", new[] { typeof(string), typeof(object) }); foreach (var prop in type.GetProperties()) { if (prop.CanWrite) { var oldSetter = prop.GetSetMethod(); if (!oldSetter.IsVirtual) { throw new ArgumentException(string.Format("The property {0} must be made virtual.", prop.Name)); } MethodBuilder pSet = typeBuilder.DefineMethod(oldSetter.Name, oldSetter.Attributes, oldSetter.ReturnType, new Type[] { prop.PropertyType }); ILGenerator pILSet = pSet.GetILGenerator(); pILSet.Emit(OpCodes.Ldarg_0); pILSet.Emit(OpCodes.Ldarg_1); pILSet.Emit(OpCodes.Call, oldSetter); pILSet.Emit(OpCodes.Ldarg_0); pILSet.Emit(OpCodes.Ldfld, propertyWatcherField); pILSet.Emit(OpCodes.Ldstr, prop.Name); pILSet.Emit(OpCodes.Ldarg_1); pILSet.Emit(OpCodes.Callvirt, setMethod); pILSet.Emit(OpCodes.Pop); pILSet.Emit(OpCodes.Ret); typeBuilder.DefineMethodOverride(pSet, oldSetter); } } return(typeBuilder.CreateType()); }
private static void ejemplo() { // An assembly consists of one or more modules, each of which // contains zero or more types. This code creates a single-module // assembly, the most common case. The module contains one type, // named "MyDynamicType", that 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.RunAndSave); // For a single-module assembly, the module name is usually // the assembly name plus an extension. ModuleBuilder mb = ab.DefineDynamicModule(aName.Name, aName.Name + ".dll"); TypeBuilder tb = mb.DefineType( "MyDynamicType", TypeAttributes.Public); // Add a private field of type int (Int32). FieldBuilder fbNumber = tb.DefineField( "m_number", typeof(int), FieldAttributes.Private); // Define a constructor that takes an integer argument and // stores it in the private field. 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 following line saves the single-module assembly. This // requires AssemblyBuilderAccess to include Save. You can now // type "ildasm MyDynamicAsm.dll" at the command prompt, and // examine the assembly. You can also write a program that has // a reference to the assembly, and use the MyDynamicType type. // ab.Save(aName.Name + ".dll"); // Because AssemblyBuilderAccess includes Run, 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. Console.WriteLine("o1.Number: {0}", pi.GetValue(o1, null)); pi.SetValue(o1, 127, null); Console.WriteLine("o1.Number: {0}", 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 }; Console.WriteLine("o1.MyMethod(22): {0}", 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 }); Console.WriteLine("o2.Number: {0}", pi.GetValue(o2, null)); }
public static Type CreateDbContextType(this ModuleBuilder moduleBuilder, string connectionKey, List <Entry> entrys) { //Define Type string typeName = $"{moduleBuilder.Assembly.GetName().Name}.{connectionKey}.Models.{connectionKey}Context"; var dbContexttype = typeof(DbContext); Type listOf = typeof(DbSet <>); TypeAttributes contextTypeAttr = TypeAttributes.Public | TypeAttributes.AutoClass | TypeAttributes.AnsiClass | TypeAttributes.BeforeFieldInit; TypeBuilder typeBuilder = moduleBuilder.DefineType(typeName, contextTypeAttr, dbContexttype); //Define Constructor Type toptionType = typeof(DbContextOptions <>); Type optionType = toptionType.MakeGenericType(typeBuilder); MethodAttributes ctormethodAttributes = MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName; ConstructorBuilder ctor1 = typeBuilder.DefineConstructor( ctormethodAttributes, CallingConventions.Standard, new[] { optionType }); ILGenerator ctor0Il = ctor1.GetILGenerator(); ConstructorInfo ctormethod = dbContexttype.GetConstructor(new[] { typeof(DbContextOptions) }); ctor0Il.Emit(OpCodes.Ldarg_0); ctor0Il.Emit(OpCodes.Ldarg_1); ctor0Il.Emit(OpCodes.Call, ctormethod); ctor0Il.Emit(OpCodes.Nop); ctor0Il.Emit(OpCodes.Nop); ctor0Il.Emit(OpCodes.Ret); //Define Property foreach (var entry in entrys) { var modelTypeName = entry.Type.Name; Type listOfTFirst = listOf.MakeGenericType(entry.Type); FieldBuilder fieldBldr = typeBuilder.DefineField("_" + modelTypeName.ToLower(), listOfTFirst, FieldAttributes.Private); PropertyBuilder propBldr = typeBuilder.DefineProperty(modelTypeName, PropertyAttributes.HasDefault, listOfTFirst, null); const MethodAttributes getSetAttr = MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.HideBySig | MethodAttributes.Virtual | MethodAttributes.NewSlot; MethodBuilder getPropMthdBldr = typeBuilder.DefineMethod("get_" + modelTypeName, getSetAttr, listOfTFirst, Type.EmptyTypes); ILGenerator getIlGenerator = getPropMthdBldr.GetILGenerator(); getIlGenerator.Emit(OpCodes.Ldarg_0); getIlGenerator.Emit(OpCodes.Ldfld, fieldBldr); getIlGenerator.Emit(OpCodes.Ret); MethodBuilder setPropMthdBldr = typeBuilder.DefineMethod("set_" + modelTypeName, getSetAttr, null, new[] { listOfTFirst }); ILGenerator setIlGenerator = setPropMthdBldr.GetILGenerator(); setIlGenerator.Emit(OpCodes.Ldarg_0); setIlGenerator.Emit(OpCodes.Ldarg_1); setIlGenerator.Emit(OpCodes.Stfld, fieldBldr); setIlGenerator.Emit(OpCodes.Ret); propBldr.SetGetMethod(getPropMthdBldr); propBldr.SetSetMethod(setPropMthdBldr); } //Define OnModelCreating MethodAttributes omcMthdAttrs = MethodAttributes.Family | MethodAttributes.Virtual | MethodAttributes.HideBySig; MethodBuilder omcMthdBldr = typeBuilder.DefineMethod("OnModelCreating", omcMthdAttrs, typeof(void), new[] { typeof(ModelBuilder) }); ILGenerator omcMthdIlGen = omcMthdBldr.GetILGenerator(); MethodInfo entityMthd = typeof(ModelBuilder).GetMethods(BindingFlags.Instance | BindingFlags.Public).FirstOrDefault(p => p.GetParameters().Count() == 0 && p.Name == "Entity" && p.IsGenericMethod && p.IsVirtual); MethodInfo ToTableMthd = typeof(RelationalEntityTypeBuilderExtensions).GetMethods(BindingFlags.Static | BindingFlags.Public).FirstOrDefault(p => p.Name == "ToTable" && p.GetParameters().Count() == 3 && p.IsGenericMethod); MethodInfo hasKeyMethod = typeof(Microsoft.EntityFrameworkCore.Metadata.Builders.EntityTypeBuilder).GetMethod("HasKey"); omcMthdIlGen.Emit(OpCodes.Nop); foreach (var entry in entrys) { string[] keys = entry.Table.Columns.Where(p => p.IsPrimaryKey).Select(p => p.ColumnName).ToArray(); int keysCount = keys.Count(); OpCode countOpCode = (OpCode)typeof(OpCodes).GetField($"Ldc_I4_{keysCount}").GetValue(null); omcMthdIlGen.Emit(OpCodes.Ldarg_1); omcMthdIlGen.Emit(OpCodes.Callvirt, entityMthd.MakeGenericMethod(entry.Type)); omcMthdIlGen.Emit(OpCodes.Ldstr, entry.Table.Name); omcMthdIlGen.Emit(OpCodes.Ldstr, entry.Table.Schema); omcMthdIlGen.Emit(OpCodes.Call, ToTableMthd.MakeGenericMethod(entry.Type)); omcMthdIlGen.Emit(countOpCode); omcMthdIlGen.Emit(OpCodes.Newarr, typeof(string)); for (int i = 0; i < keysCount; i++) { OpCode itemOpCode = (OpCode)typeof(OpCodes).GetField($"Ldc_I4_{i}").GetValue(null); omcMthdIlGen.Emit(OpCodes.Dup); omcMthdIlGen.Emit(itemOpCode); omcMthdIlGen.Emit(OpCodes.Ldstr, keys[i]); omcMthdIlGen.Emit(OpCodes.Stelem_Ref); } omcMthdIlGen.Emit(OpCodes.Callvirt, hasKeyMethod); omcMthdIlGen.Emit(OpCodes.Pop); } omcMthdIlGen.Emit(OpCodes.Ret); var dbContextOmcMthd = typeof(DbContext).GetMethods(BindingFlags.NonPublic | BindingFlags.Instance).FirstOrDefault(p => p.Name == "OnModelCreating" && p.IsVirtual && p.GetParameters().Count() == 1); typeBuilder.DefineMethodOverride(omcMthdBldr, dbContextOmcMthd); return(typeBuilder.CreateType()); }
internal static CodeEmitter Create(ConstructorBuilder cb) { return new CodeEmitter(cb.GetILGenerator()); }
internal MyConstructorBuilder() { // <Snippet1> // <Snippet2> // <Snippet3> MethodBuilder myMethodBuilder = null; AppDomain myCurrentDomain = AppDomain.CurrentDomain; // Create assembly in current CurrentDomain AssemblyName myAssemblyName = new AssemblyName(); myAssemblyName.Name = "TempAssembly"; // Create a dynamic assembly myAssemblyBuilder = myCurrentDomain.DefineDynamicAssembly (myAssemblyName, AssemblyBuilderAccess.RunAndSave); // Create a dynamic module in the assembly. myModuleBuilder = myAssemblyBuilder.DefineDynamicModule("TempModule"); FieldInfo myFieldInfo = myModuleBuilder.DefineUninitializedData("myField", 2, FieldAttributes.Public); // Create a type in the module TypeBuilder myTypeBuilder = myModuleBuilder.DefineType("TempClass", TypeAttributes.Public); FieldBuilder myGreetingField = myTypeBuilder.DefineField("Greeting", typeof(String), FieldAttributes.Public); Type[] myConstructorArgs = { typeof(String) }; // Define a constructor of the dynamic class. ConstructorBuilder myConstructor = myTypeBuilder.DefineConstructor( MethodAttributes.Public, CallingConventions.Standard, myConstructorArgs); PermissionSet myPset = new PermissionSet(PermissionState.Unrestricted); // Add declarative security to the constructor. Console.WriteLine("Adding declarative security to the constructor....."); Console.WriteLine("The Security action to be taken is \"DENY\" and" + " Permission set is \"UNRESTRICTED\"."); myConstructor.AddDeclarativeSecurity(SecurityAction.Deny, myPset); // </Snippet3> MethodAttributes myMethodAttributes = myConstructor.Attributes; Type myAttributeType = typeof(MethodAttributes); int myAttribValue = (int)myMethodAttributes; if (!myAttributeType.IsEnum) { Console.WriteLine("This is not an Enum"); } FieldInfo[] myFieldInfo1 = myAttributeType.GetFields(BindingFlags.Public | BindingFlags.Static); Console.WriteLine("The Field info names of the Attributes for the constructor are:"); for (int i = 0; i < myFieldInfo1.Length; i++) { int myFieldValue = (Int32)myFieldInfo1[i].GetValue(null); if ((myFieldValue & myAttribValue) == myFieldValue) { Console.WriteLine(" " + myFieldInfo1[i].Name); } } Type myType2 = myConstructor.DeclaringType; Console.WriteLine("The declaring type is : " + myType2.ToString()); // </Snippet2> ParameterBuilder myParameterBuilder1 = myConstructor.DefineParameter(1, ParameterAttributes.Out, "My Parameter Name1"); Console.WriteLine("The name of the parameter is : " + myParameterBuilder1.Name); if (myParameterBuilder1.IsIn) { Console.WriteLine(myParameterBuilder1.Name + " is Input parameter."); } else { Console.WriteLine(myParameterBuilder1.Name + " is not Input Parameter."); } ParameterBuilder myParameterBuilder2 = myConstructor.DefineParameter(1, ParameterAttributes.In, "My Parameter Name2"); Console.WriteLine("The Parameter name is : " + myParameterBuilder2.Name); if (myParameterBuilder2.IsIn) { Console.WriteLine(myParameterBuilder2.Name + " is Input parameter."); } else { Console.WriteLine(myParameterBuilder2.Name + " is not Input Parameter."); } // </Snippet1> // Generate MSIL for the method, call its base class constructor and store the arguments // in the private field. ILGenerator myILGenerator3 = myConstructor.GetILGenerator(); myILGenerator3.Emit(OpCodes.Ldarg_0); ConstructorInfo myConstructorInfo = typeof(Object).GetConstructor(new Type[0]); myILGenerator3.Emit(OpCodes.Call, myConstructorInfo); myILGenerator3.Emit(OpCodes.Ldarg_0); myILGenerator3.Emit(OpCodes.Ldarg_1); myILGenerator3.Emit(OpCodes.Stfld, myGreetingField); myILGenerator3.Emit(OpCodes.Ret); // Add a method to the type. myMethodBuilder = myTypeBuilder.DefineMethod ("HelloWorld", MethodAttributes.Public, null, null); // Generate MSIL for the method. ILGenerator myILGenerator2 = myMethodBuilder.GetILGenerator(); myILGenerator2.EmitWriteLine("Hello World from global"); myILGenerator2.Emit(OpCodes.Ret); myModuleBuilder.CreateGlobalFunctions(); myType1 = myTypeBuilder.CreateType(); }