public override void Populate(IDefinitionManager definitionManager, IPlanet planet, IChunkColumn column00, IChunkColumn column10, IChunkColumn column01, IChunkColumn column11) { // Tree Definitions initialisieren if (treeDefinitions == null) { treeDefinitions = definitionManager.GetDefinitions<ITreeDefinition>().OrderBy(d => d.Order).ToArray(); foreach (var treeDefinition in treeDefinitions) treeDefinition.Init(definitionManager); } int salt = (column00.Index.X & 0xffff) + ((column00.Index.Y & 0xffff) << 16); Random random = new Random(planet.Seed + salt); Index3 sample = new Index3(column00.Index.X * Chunk.CHUNKSIZE_X, column00.Index.Y * Chunk.CHUNKSIZE_Y, column00.Heights[0, 0]); foreach (var treeDefinition in treeDefinitions) { int density = treeDefinition.GetDensity(planet, sample); if (density <= 0) continue; for (int i = 0; i < density; i++) { int x = random.Next(Chunk.CHUNKSIZE_X / 2, Chunk.CHUNKSIZE_X * 3 / 2); int y = random.Next(Chunk.CHUNKSIZE_Y / 2, Chunk.CHUNKSIZE_Y * 3 / 2); int z = LocalBuilder.GetSurfaceHeight(column00, column10, column01, column11, x, y); LocalBuilder builder = new LocalBuilder(x, y, z + 1, column00, column10, column01, column11); treeDefinition.PlantTree(definitionManager, planet, new Index3(x, y, z), builder, random.Next(int.MaxValue)); } } }
public override void PlantTree(IDefinitionManager definitionManager, IPlanet planet, Index3 index, LocalBuilder builder, int seed) { ushort ground = builder.GetBlock(0, 0, -1); if (ground == water) return; Random rand = new Random(seed); int height = rand.Next(2, 4); for (int i = 0; i < height; i++) builder.SetBlock(0, 0, i, cactus); }
public override void PlantTree(IDefinitionManager definitionManager, IPlanet planet, Index3 index, LocalBuilder builder, int seed) { ushort ground = builder.GetBlock(0, 0, -1); if (ground == water) return; Random rand = new Random(seed); int height = rand.Next(3, 5); int radius = rand.Next(3, height); builder.FillSphere(0, 0, height, radius, leave); for (int i = 0; i < height + 2; i++) { builder.SetBlock(0, 0, 0 + i, wood); } }
public bool TryEmitSerialiseCode(ILGenerator ilg, ThrowBlockGatherer throwBlocks, ICollection <string> errors, LocalBuilder value, LocalBuilder packer, LocalBuilder contextLocal, DasherContext context) { // write the string form of the value ilg.Emit(OpCodes.Ldloc, packer); ilg.Emit(OpCodes.Ldloca, value); ilg.Emit(OpCodes.Call, Methods.Decimal_ToString); ilg.Emit(OpCodes.Call, Methods.Packer_Pack_String); return(true); }
private static Type CreateInterfaceType() { Type type = typeof(I); // Get the current application domain for the current thread. AppDomain myCurrentDomain = AppDomain.CurrentDomain; AssemblyName myAssemblyName = new AssemblyName() { Name = "TempAssembly" }; // Define a dynamic assembly in the current application domain. AssemblyBuilder myAssemblyBuilder = myCurrentDomain.DefineDynamicAssembly(myAssemblyName, AssemblyBuilderAccess.Run); // Define a dynamic module in this assembly. ModuleBuilder myModuleBuilder = myAssemblyBuilder.DefineDynamicModule("TempModule"); // Define a runtime class with specified name and attributes. TypeBuilder typeBuilder = myModuleBuilder.DefineType("ImplOf" + type.Name, TypeAttributes.Class | TypeAttributes.Public); typeBuilder.AddInterfaceImplementation(type); // Create Constructor ConstructorInfo baseConstructorInfo = typeof(object).GetConstructor(new Type[0]); ConstructorBuilder constructorBuilder = typeBuilder.DefineConstructor(MethodAttributes.Public, CallingConventions.Standard, Type.EmptyTypes); ILGenerator ilGenerator = constructorBuilder.GetILGenerator(); ilGenerator.Emit(OpCodes.Ldarg_0); // Load "this" ilGenerator.Emit(OpCodes.Call, baseConstructorInfo); // Call the base constructor ilGenerator.Emit(OpCodes.Ret); // return // actor field var actorField = typeBuilder.DefineField("actorRef", typeof(IActor), FieldAttributes.Public); // what methods ? List <MethodInfo> methods = new List <MethodInfo>(); AddMethodsToList(methods, type); // properties ? List <PropertyInfo> properties = new List <PropertyInfo>(); AddPropertiesToList(properties, type); // add properties foreach (PropertyInfo pi in properties) { string piName = pi.Name; Type propertyType = pi.PropertyType; // Create underlying field; all properties have a field of the same type FieldBuilder field = typeBuilder.DefineField("_" + piName, propertyType, FieldAttributes.Private); // If there is a getter in the interface, create a getter in the new type MethodInfo getMethod = pi.GetGetMethod(); if (null != getMethod) { // This will prevent us from creating a default method for the property's getter methods.Remove(getMethod); // Now we will generate the getter method MethodBuilder methodBuilder = typeBuilder.DefineMethod(getMethod.Name, MethodAttributes.Public | MethodAttributes.Virtual, propertyType, Type.EmptyTypes); // The ILGenerator class is used to put op-codes (similar to assembly) // into the method ilGenerator = methodBuilder.GetILGenerator(); // These are the op-codes, (similar to assembly) ilGenerator.Emit(OpCodes.Ldarg_0); // Load "this" // Load the property's underlying field onto the stack ilGenerator.Emit(OpCodes.Ldfld, field); ilGenerator.Emit(OpCodes.Ret); // Return the value on the stack // We need to associate our new type's method with the // getter method in the interface typeBuilder.DefineMethodOverride(methodBuilder, getMethod); } // If there is a setter in the interface, create a setter in the new type MethodInfo setMethod = pi.GetSetMethod(); if (null != setMethod) { // This will prevent us from creating a default method for the property's setter methods.Remove(setMethod); // Now we will generate the setter method MethodBuilder methodBuilder = typeBuilder.DefineMethod (setMethod.Name, MethodAttributes.Public | MethodAttributes.Virtual, typeof(void), new Type[] { pi.PropertyType }); // The ILGenerator class is used to put op-codes (similar to assembly) // into the method ilGenerator = methodBuilder.GetILGenerator(); // These are the op-codes, (similar to assembly) ilGenerator.Emit(OpCodes.Ldarg_0); // Load "this" ilGenerator.Emit(OpCodes.Ldarg_1); // Load "value" onto the stack // Set the field equal to the "value" on the stack ilGenerator.Emit(OpCodes.Stfld, field); ilGenerator.Emit(OpCodes.Ret); // Return nothing // We need to associate our new type's method with the // setter method in the interface typeBuilder.DefineMethodOverride(methodBuilder, setMethod); } } // add method foreach (MethodInfo methodInfo in methods) { // Get the return type and argument types Type returnType = methodInfo.ReturnType; List <Type> argumentTypes = new List <Type>(); foreach (ParameterInfo parameterInfo in methodInfo.GetParameters()) { argumentTypes.Add(parameterInfo.ParameterType); } // Define the method MethodBuilder methodBuilder = typeBuilder.DefineMethod (methodInfo.Name, MethodAttributes.Public | MethodAttributes.Virtual, returnType, argumentTypes.ToArray()); // The ILGenerator class is used to put op-codes // (similar to assembly) into the method ilGenerator = methodBuilder.GetILGenerator(); // If there's a return type, create a default value or null to return if (returnType != typeof(void)) { // send message with a future param // this declares the local object, int, long, float, etc. LocalBuilder localBuilder = ilGenerator.DeclareLocal(returnType); var constructorInfo = returnType.GetConstructor(Type.EmptyTypes); var localMethodinfo = typeof(ActorProxyModel <T>).GetMethod("SendMethodAndParam"); // build local future ilGenerator.Emit(OpCodes.Newobj, constructorInfo); ilGenerator.Emit(OpCodes.Stloc_0); ilGenerator.Emit(OpCodes.Ldarg_0); // this ilGenerator.Emit(OpCodes.Ldfld, actorField); // actor ref ilGenerator.Emit(OpCodes.Ldstr, methodInfo.Name); ilGenerator.Emit(OpCodes.Ldloc_0); // future ilGenerator.Emit(OpCodes.Callvirt, localMethodinfo); // load the value on the stack to return ilGenerator.Emit(OpCodes.Ldloc, localBuilder); ilGenerator.Emit(OpCodes.Ret); // return } else { var localMethodinfo = typeof(ActorProxyModel <T>).GetMethod("SendMethodAndParam"); ilGenerator.Emit(OpCodes.Ldarg_0); // this ilGenerator.Emit(OpCodes.Ldfld, actorField); // actor ref ilGenerator.Emit(OpCodes.Ldstr, methodInfo.Name); ilGenerator.Emit(OpCodes.Ldarg_1); // message ilGenerator.Emit(OpCodes.Callvirt, localMethodinfo); ilGenerator.Emit(OpCodes.Ret); } // We need to associate our new type's method with the method in the interface typeBuilder.DefineMethodOverride(methodBuilder, methodInfo); } Type createdType = typeBuilder.CreateType(); // InterfaceImplementations[type] = createdType; return(createdType); }
public _Local(CodeGen owner, LocalBuilder var) { _owner = owner; _var = var; _t = var.LocalType; }
private void BuildIsNull( MemberInfo mi, TypeBuilderHelper nestedType, Type memberType) { var methodType = mi.DeclaringType; var getMethod = null as MethodInfo; var isNullable = TypeHelper.IsNullable(memberType); var isValueType = (!isNullable && memberType.IsValueType); if (!isValueType && mi is PropertyInfo) { getMethod = ((PropertyInfo)mi).GetGetMethod(); if (getMethod == null) { if (_type != _originalType) { getMethod = _type.GetMethod("get_" + mi.Name); methodType = _type; } if (getMethod == null) { return; } } } var methodInfo = _memberAccessor.GetMethod("IsNull"); if (methodInfo == null) { return; } var method = nestedType.DefineMethod(methodInfo); var emit = method.Emitter; if (isValueType) { emit .ldc_i4_0 .end() ; } else { LocalBuilder locObj = null; if (isNullable) { locObj = method.Emitter.DeclareLocal(memberType); } emit .ldarg_1 .castType(methodType) .end(); if (mi is FieldInfo) { emit.ldfld((FieldInfo)mi); } else { emit.callvirt(getMethod); } if (isNullable) { emit .stloc(locObj) .ldloca(locObj) .call(memberType, "get_HasValue") .ldc_i4_0 .ceq .end(); } else { emit .ldnull .ceq .end(); } } emit .ret() ; }
static void EmitPtrAndFlagsStore(ILGenerator ilg, LocalBuilder bufLocal, int argnum, IntPtr ptr, sbyte flags) { //= bufLocal[argnum].ptr = ptr; ilg.Emit(OpCodes.Ldloc, bufLocal); ilg.Emit(OpCodes.Ldc_I4, argnum * VARIANT_SIZE + 8); ilg.Emit(OpCodes.Add); ilg.Emit(OpCodes.Ldc_I4, ptr.ToInt32()); ilg.Emit(OpCodes.Stind_I4); //= bufLocal[argnum].flags = flags; ilg.Emit(OpCodes.Ldloc, bufLocal); ilg.Emit(OpCodes.Ldc_I4, argnum * VARIANT_SIZE + 13); ilg.Emit(OpCodes.Add); ilg.Emit(OpCodes.Ldc_I4, (Int32)flags); ilg.Emit(OpCodes.Stind_I1); }
/// <summary> /// Constructor /// </summary> /// <param name="Name">Local object name</param> /// <param name="LocalType">Local type</param> public DefineLocal(string Name, Type LocalType) : base() { Result = new LocalBuilder(Utilities.Reflection.Emit.BaseClasses.MethodBase.CurrentMethod, Name, LocalType); }
private void EmitLiftedBinaryArithmetic(ExpressionType op, Type leftType, Type rightType, Type resultType) { bool leftIsNullable = leftType.IsNullable(); bool rightIsNullable = rightType.IsNullable(); Debug.Assert(leftIsNullable || rightIsNullable); Label labIfNull = _ilg.DefineLabel(); Label labEnd = _ilg.DefineLabel(); LocalBuilder locLeft = GetLocal(leftType); LocalBuilder locRight = GetLocal(rightType); LocalBuilder locResult = GetLocal(resultType); // store values (reverse order since they are already on the stack) _ilg.Emit(OpCodes.Stloc, locRight); _ilg.Emit(OpCodes.Stloc, locLeft); // test for null // don't use short circuiting if (leftIsNullable) { _ilg.Emit(OpCodes.Ldloca, locLeft); _ilg.EmitHasValue(leftType); } if (rightIsNullable) { _ilg.Emit(OpCodes.Ldloca, locRight); _ilg.EmitHasValue(rightType); if (leftIsNullable) { _ilg.Emit(OpCodes.And); } } _ilg.Emit(OpCodes.Brfalse_S, labIfNull); // do op on values if (leftIsNullable) { _ilg.Emit(OpCodes.Ldloca, locLeft); _ilg.EmitGetValueOrDefault(leftType); } else { _ilg.Emit(OpCodes.Ldloc, locLeft); } if (rightIsNullable) { _ilg.Emit(OpCodes.Ldloca, locRight); _ilg.EmitGetValueOrDefault(rightType); } else { _ilg.Emit(OpCodes.Ldloc, locRight); } //RELEASING locLeft locRight FreeLocal(locLeft); FreeLocal(locRight); EmitBinaryOperator(op, leftType.GetNonNullable(), rightType.GetNonNullable(), resultType.GetNonNullable(), liftedToNull: false); // construct result type ConstructorInfo ci = resultType.GetConstructor(new[] { resultType.GetNonNullable() }); // ReSharper disable once AssignNullToNotNullAttribute _ilg.Emit(OpCodes.Newobj, ci); _ilg.Emit(OpCodes.Stloc, locResult); _ilg.Emit(OpCodes.Br_S, labEnd); // if null then create a default one _ilg.MarkLabel(labIfNull); _ilg.Emit(OpCodes.Ldloca, locResult); _ilg.Emit(OpCodes.Initobj, resultType); _ilg.MarkLabel(labEnd); _ilg.Emit(OpCodes.Ldloc, locResult); //RELEASING locResult FreeLocal(locResult); }
public static Instruction Create(Specials specials, LocalBuilder lvar) { Instruction i = new Instruction(); i.type = InstructionType.Special; i.operand = lvar; i.operandType = typeof(LocalBuilder); i.special = specials; return i; }
//Examples of generated code // public static XWeak constructor1(XComponentContext ctx) // { // XMultiComponentFactory factory = ctx.getServiceManager(); // if (factory == null) // throw new com.sun.star.uno.DeploymentException("bla", null); // return (XWeak) factory.createInstanceWithContext("service_specifier", ctx); // } // public static XWeak constructor2(XComponentContext ctx, int a, int b) // { // XMultiComponentFactory factory = ctx.getServiceManager(); // if (factory == null) // throw new com.sun.star.uno.DeploymentException("bla", null); // Any a1; // a1 = new Any( typeof(int), a); // Any a2; // a2 = new Any( typeof(int), b); // Any[] arAny = new Any[2]; // arAny[0] = a1; // arAny[1] = a2; // return (XWeak) factory.createInstanceWithArgumentsAndContext("service_specifier", arAny, ctx); // } // public static XWeak constructor3(XComponentContext ctx, params Any[] c) // { // XMultiComponentFactory factory = ctx.getServiceManager(); // if (factory == null) // throw new com.sun.star.uno.DeploymentException("bla", null); // return (XWeak) factory.createInstanceWithArgumentsAndContext("service_specifier", c, ctx); // } Type complete_service_type(service_entry entry) { TypeBuilder type_builder = entry.m_type_builder; XServiceTypeDescription2 xServiceType = entry.m_xType; // Create the private default constructor ConstructorBuilder ctor_builder = type_builder.DefineConstructor( (MethodAttributes.Private | MethodAttributes.HideBySig | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName), CallingConventions.Standard, null); ILGenerator code = ctor_builder.GetILGenerator(); code.Emit(OpCodes.Ldarg_0); // push this code.Emit(OpCodes.Call, type_builder.BaseType.GetConstructor(new Type[0])); code.Emit(OpCodes.Ret); // Create the service constructors. // optain the interface which makes up this service, it is the // return type of the constructor functions XInterfaceTypeDescription2 xIfaceType = xServiceType.getInterface() as XInterfaceTypeDescription2; if (xIfaceType == null) xIfaceType = resolveInterfaceTypedef(xServiceType.getInterface()); Type retType = get_type(xIfaceType); // Create the ConstructorInfo for a DeploymentException Type typeDeploymentExc = get_type("unoidl.com.sun.star.uno.DeploymentException", true); Type[] typeCtor = new Type[] { typeof(System.String), typeof(System.Object) }; ConstructorInfo ctorDeploymentException = typeDeploymentExc.GetConstructor(typeCtor); XServiceConstructorDescription[] ctors = xServiceType.getConstructors(); Type type_uno_exception = get_type("unoidl.com.sun.star.uno.Exception", true); for (int i = ctors.Length - 1; i >= 0; --i) { bool bParameterArray = false; Type typeAny = typeof(uno.Any); XServiceConstructorDescription ctorDes = ctors[i]; // obtain the parameter types XParameter[] xParams = ctorDes.getParameters(); Type[] typeParameters = new Type[xParams.Length + 1]; typeParameters[0] = get_type("unoidl.com.sun.star.uno.XComponentContext", true); for (int iparam = 0; iparam != xParams.Length; ++iparam) { if (xParams[iparam].isRestParameter()) typeParameters[iparam + 1] = typeof(uno.Any[]); else typeParameters[iparam + 1] = get_type(xParams[iparam].getType()); } // define method string ctorName; if (ctorDes.isDefaultConstructor()) ctorName = "create"; else ctorName = ctorDes.getName(); MethodBuilder method_builder = type_builder.DefineMethod( ctorName, (MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.Static), retType, typeParameters); // define UNO exception attribute (exceptions) CustomAttributeBuilder attrBuilder = get_service_exception_attribute(ctorDes); if (attrBuilder != null) method_builder.SetCustomAttribute(attrBuilder); // define parameter attributes (paramarray), names etc. // The first parameter is the XComponentContext, which cannot be // obtained from reflection. // The context is not part of the idl description /* ParameterBuilder param_builder = */ method_builder.DefineParameter( 1, ParameterAttributes.In, "the_context"); ParameterBuilder[] parameterBuilders = new ParameterBuilder[xParams.Length]; for (int iparam = 0; iparam != xParams.Length + 1; ++iparam) { parameterBuilders[iparam] = method_builder.DefineParameter( iparam + 2, ParameterAttributes.In, xParams[iparam].getName()); if (xParams[iparam].isRestParameter()) { bParameterArray = true; // set the ParameterArrayAttribute ConstructorInfo ctor_info = typeof(System.ParamArrayAttribute).GetConstructor( new Type[0]); CustomAttributeBuilder attr_builder = new CustomAttributeBuilder(ctor_info, new object[0]); parameterBuilders[iparam].SetCustomAttribute(attr_builder); break; } } ILGenerator ilGen = method_builder.GetILGenerator(); // Define locals // XMultiComponentFactory LocalBuilder local_factory = ilGen.DeclareLocal( get_type("unoidl.com.sun.star.lang.XMultiComponentFactory", true)); // The return type LocalBuilder local_return_val = ilGen.DeclareLocal(retType); // Obtain the XMultiComponentFactory and throw an exception if we // do not get one ilGen.Emit(OpCodes.Ldarg_0); MethodInfo methodGetServiceManager = get_type( "unoidl.com.sun.star.uno.XComponentContext", true) .GetMethod("getServiceManager"); ilGen.Emit(OpCodes.Callvirt, methodGetServiceManager); ilGen.Emit(OpCodes.Stloc, local_factory); ilGen.Emit(OpCodes.Ldloc, local_factory); Label label1 = ilGen.DefineLabel(); ilGen.Emit(OpCodes.Brtrue, label1); ilGen.Emit(OpCodes.Ldstr, String.Format("The service unoidl.{0} could not be created. The context failed to supply the service manager.", xServiceType.getName())); ilGen.Emit(OpCodes.Ldarg_0); ilGen.Emit(OpCodes.Newobj, ctorDeploymentException); ilGen.Emit(OpCodes.Throw); ilGen.MarkLabel(label1); // We create a try/catch around the createInstanceWithContext, // etc. functions // There are 3 cases // 1. function do not specify exceptions. Then // RuntimeExceptions are retrhown and other exceptions // produce a DeploymentException. // 2. function specify Exception. Then all exceptions fly // through // 3. function specifies exceptions but no Exception. Then // these are rethrown and other exceptions, except // RuntimeException, produce a deployment exception. // In case there are no parameters we call // XMultiComponentFactory.createInstanceWithContext ArrayList exceptionTypes = get_service_ctor_method_exceptions_reduced( ctorDes.getExceptions()); if (! exceptionTypes.Contains(type_uno_exception)) { ilGen.BeginExceptionBlock(); } if (xParams.Length == 0) { ilGen.Emit(OpCodes.Ldloc, local_factory); ilGen.Emit(OpCodes.Ldstr, to_cts_name(xServiceType.getName())); ilGen.Emit(OpCodes.Ldarg_0); MethodInfo methodCIWAAC = local_factory.LocalType.GetMethod( "createInstanceWithArgumentsAndContext"); ilGen.Emit(OpCodes.Callvirt, methodCIWAAC); } else if (bParameterArray) { // Service constructor with parameter array ilGen.Emit(OpCodes.Ldloc, local_factory); ilGen.Emit(OpCodes.Ldstr, to_cts_name(xServiceType.getName())); ilGen.Emit(OpCodes.Ldarg_1); ilGen.Emit(OpCodes.Ldarg_0); MethodInfo methodCIWAAC = local_factory.LocalType.GetMethod( "createInstanceWithArgumentsAndContext"); ilGen.Emit(OpCodes.Callvirt, methodCIWAAC); } else { // Any param1, Any param2, etc. // For each parameter, except the component context, and // the parameter array an Any is created. LocalBuilder[] localAnys = new LocalBuilder[xParams.Length]; for (int iparam = 0; iparam < xParams.Length; ++iparam) { localAnys[iparam] = ilGen.DeclareLocal(typeAny); } // Any[]. This array is filled with the created Anys // which contain the parameters and the values // contained in the parameter array LocalBuilder local_anyParams = ilGen.DeclareLocal(typeof(uno.Any[])); // Create the Any for every argument, except for the // parameter array. localAnys contains the LocalBuilder for // all these parameters. We call the ctor Any(Type, Object) Type[] typesCtorAny = { typeof(System.Type), typeof(System.Object) }; ConstructorInfo ctorAny = typeAny.GetConstructor(typesCtorAny); for (int j = 0; j < localAnys.Length; ++j) { ilGen.Emit(OpCodes.Ldloca, localAnys[j]); ilGen.Emit(OpCodes.Ldtoken, typeParameters[j+1]); Type[] typeParams = { typeof(System.RuntimeTypeHandle) }; ilGen.Emit(OpCodes.Call, typeof(System.Type).GetMethod( "GetTypeFromHandle", typeParams)); ilGen.Emit(OpCodes.Ldarg, j + 1); // if the parameter is a value type then we need // to box it, because the Any ctor takes an Object if (typeParameters[j+1].IsValueType) ilGen.Emit(OpCodes.Box, typeParameters[j+1]); ilGen.Emit(OpCodes.Call, ctorAny); } // Create the Any[] that is passed to the // createInstanceWithContext[AndArguments] function ilGen.Emit(OpCodes.Ldc_I4, localAnys.Length); ilGen.Emit(OpCodes.Newarr, typeAny); ilGen.Emit(OpCodes.Stloc, local_anyParams); // Assign all anys created from the parameters array // to the Any[] for (int j = 0; j < localAnys.Length; ++j) { ilGen.Emit(OpCodes.Ldloc, local_anyParams); ilGen.Emit(OpCodes.Ldc_I4, j); ilGen.Emit(OpCodes.Ldelema, typeAny); ilGen.Emit(OpCodes.Ldloc, localAnys[j]); ilGen.Emit(OpCodes.Stobj, typeAny); } // call createInstanceWithContextAndArguments ilGen.Emit(OpCodes.Ldloc, local_factory); ilGen.Emit(OpCodes.Ldstr, to_cts_name(xServiceType.getName())); ilGen.Emit(OpCodes.Ldloc, local_anyParams); ilGen.Emit(OpCodes.Ldarg_0); MethodInfo methodCIWAAC = local_factory.LocalType.GetMethod( "createInstanceWithArgumentsAndContext"); ilGen.Emit(OpCodes.Callvirt, methodCIWAAC); } // cast the object returned by the functions // createInstanceWithContext or // createInstanceWithArgumentsAndContext to the interface type ilGen.Emit(OpCodes.Castclass, retType); ilGen.Emit(OpCodes.Stloc, local_return_val); // catch exceptions thrown by createInstanceWithArgumentsAndContext // and createInstanceWithContext if (!exceptionTypes.Contains(type_uno_exception)) { // catch (unoidl.com.sun.star.uno.RuntimeException) {throw;} ilGen.BeginCatchBlock( get_type( "unoidl.com.sun.star.uno.RuntimeException", true)); ilGen.Emit(OpCodes.Pop); ilGen.Emit(OpCodes.Rethrow); // catch and rethrow all other defined Exceptions foreach (Type excType in exceptionTypes) { if (excType.IsInstanceOfType( get_type( "unoidl.com.sun.star.uno.RuntimeException", true))) { // we have a catch for RuntimeException already defined continue; } // catch Exception and rethrow ilGen.BeginCatchBlock(excType); ilGen.Emit(OpCodes.Pop); ilGen.Emit(OpCodes.Rethrow); } // catch (unoidl.com.sun.star.uno.Exception) // { throw DeploymentException... } ilGen.BeginCatchBlock(type_uno_exception); // define the local variable that keeps the exception LocalBuilder local_exception = ilGen.DeclareLocal( type_uno_exception); // Store the exception ilGen.Emit(OpCodes.Stloc, local_exception); // prepare the construction of the exception ilGen.Emit(OpCodes.Ldstr, "The context (com.sun.star.uno.XComponentContext)" + "failed to supply the service " + to_cts_name(xServiceType.getName()) + ": "); // add to the string the Exception.Message ilGen.Emit(OpCodes.Ldloc, local_exception); ilGen.Emit(OpCodes.Callvirt, type_uno_exception.GetProperty("Message") .GetGetMethod()); Type[] concatParams = new Type[] { typeof(System.String), typeof(System.String) }; ilGen.Emit(OpCodes.Call, typeof(System.String).GetMethod("Concat", concatParams)); // load context argument ilGen.Emit(OpCodes.Ldarg_0); ilGen.Emit(OpCodes.Newobj, ctorDeploymentException); ilGen.Emit(OpCodes.Throw); // Exception(typeDeploymentExc); ilGen.EndExceptionBlock(); } // Check if the service instance was create and throw an // exception if not. Label label_service_created = ilGen.DefineLabel(); ilGen.Emit(OpCodes.Ldloc, local_return_val); ilGen.Emit(OpCodes.Brtrue_S, label_service_created); ilGen.Emit(OpCodes.Ldstr, "The context (com.sun.star.uno.XComponentContext)" + "failed to supply the service unoidl." + to_cts_name(xServiceType.getName()) + "."); ilGen.Emit(OpCodes.Ldarg_0); ilGen.Emit(OpCodes.Newobj, ctorDeploymentException); ilGen.Emit(OpCodes.Throw); // Exception(typeDeploymentExc); ilGen.MarkLabel(label_service_created); ilGen.Emit(OpCodes.Ldloc, local_return_val); ilGen.Emit(OpCodes.Ret); } // remove from incomplete types map m_incomplete_services.Remove(type_builder.FullName); if (Climaker.g_verbose) { Console.WriteLine("> emitting service type {0}", type_builder.FullName); } return type_builder.CreateType(); }
void EmitProtoFull(RHC rhc, ObjExpr objx, CljILGen ilg) { Label onLabel = ilg.DefineLabel(); Label callLabel = ilg.DefineLabel(); Label endLabel = ilg.DefineLabel(); Var v = ((VarExpr)_fexpr).Var; Expr e = (Expr)_args.nth(0); e.Emit(RHC.Expression, objx, ilg); // target ilg.Emit(OpCodes.Dup); // target, target LocalBuilder targetTemp = ilg.DeclareLocal(typeof(Object)); GenContext.SetLocalName(targetTemp, "target"); ilg.Emit(OpCodes.Stloc, targetTemp); // target ilg.Emit(OpCodes.Call, Compiler.Method_Util_classOf); // class ilg.EmitLoadArg(0); // class, this ilg.EmitFieldGet(objx.CachedTypeField(_siteIndex)); // class, cached-class ilg.Emit(OpCodes.Beq, callLabel); // if (_protocolOn != null) { ilg.Emit(OpCodes.Ldloc, targetTemp); // target ilg.Emit(OpCodes.Isinst, _protocolOn); // null or target ilg.Emit(OpCodes.Ldnull); // (null or target), null ilg.Emit(OpCodes.Cgt_Un); // (0 or 1) ilg.Emit(OpCodes.Brtrue, onLabel); } ilg.Emit(OpCodes.Ldloc, targetTemp); // target ilg.Emit(OpCodes.Call, Compiler.Method_Util_classOf); // class LocalBuilder typeTemp = ilg.DeclareLocal(typeof(Type)); GenContext.SetLocalName(typeTemp, "type"); ilg.Emit(OpCodes.Stloc, typeTemp); // (typeType <= class) ilg.EmitLoadArg(0); // this ilg.Emit(OpCodes.Ldloc, typeTemp); // this, class ilg.EmitFieldSet(objx.CachedTypeField(_siteIndex)); // ilg.MarkLabel(callLabel); objx.EmitVar(ilg, v); // var ilg.Emit(OpCodes.Call, Compiler.Method_Var_getRawRoot); // proto-fn ilg.Emit(OpCodes.Castclass, typeof(AFunction)); ilg.Emit(OpCodes.Ldloc, targetTemp); // proto-fn, target EmitArgsAndCall(1, rhc, objx, ilg); ilg.Emit(OpCodes.Br, endLabel); ilg.MarkLabel(onLabel); ilg.Emit(OpCodes.Ldloc, targetTemp); // target if (_protocolOn != null) { ilg.Emit(OpCodes.Castclass, _protocolOn); MethodExpr.EmitTypedArgs(objx, ilg, _onMethod.GetParameters(), RT.subvec(_args, 1, _args.count())); //if (rhc == RHC.Return) //{ // ObjMethod2 method = (ObjMethod)Compiler.MethodVar.deref(); // method.EmitClearLocals(context); //} ilg.Emit(OpCodes.Callvirt, _onMethod); HostExpr.EmitBoxReturn(objx, ilg, _onMethod.ReturnType); } ilg.MarkLabel(endLabel); }
public abstract void PlantTree(IDefinitionManager definitionManager, IPlanet planet, Index3 index, LocalBuilder builder, int seed);
static void EmitOutParamPrep(ILGenerator ilg, LocalBuilder bufLocal, TypeInfo.TypeDescriptor type, int argnum) { ilg.Emit(OpCodes.Nop); ilg.Emit(OpCodes.Ldloc, bufLocal); ilg.Emit(OpCodes.Ldc_I4, argnum * VARIANT_SIZE + 13); ilg.Emit(OpCodes.Add); ilg.Emit(OpCodes.Ldc_I4, 1); // PTR_IS_DATA ilg.Emit(OpCodes.Stind_I1); ilg.Emit(OpCodes.Ldloc, bufLocal); ilg.Emit(OpCodes.Ldc_I4, argnum * VARIANT_SIZE + 8); // offsetof(ptr) ilg.Emit(OpCodes.Add); ilg.Emit(OpCodes.Ldloc, bufLocal); ilg.Emit(OpCodes.Ldc_I4, argnum * VARIANT_SIZE + 0); // offsetof(val) ilg.Emit(OpCodes.Add); ilg.Emit(OpCodes.Stind_I4); /* XXX 64-bitness! */ }
static void EmitTypeStore(ILGenerator ilg, LocalBuilder bufLocal, TypeInfo.TypeDescriptor t, int argnum) { ilg.Emit(OpCodes.Ldloc, bufLocal); ilg.Emit(OpCodes.Ldc_I4, argnum * VARIANT_SIZE + 12); ilg.Emit(OpCodes.Add); ilg.Emit(OpCodes.Ldc_I4, (Int32)t.tag); ilg.Emit(OpCodes.Stind_I4); }
internal void Emit(OpCode opcode, LocalBuilder local) { _ilg.Emit(opcode, local); int tempVal = local.LocalIndex; if (opcode.Equals(OpCodes.Ldloc)) { switch (tempVal) { case 0: opcode = OpCodes.Ldloc_0; break; case 1: opcode = OpCodes.Ldloc_1; break; case 2: opcode = OpCodes.Ldloc_2; break; case 3: opcode = OpCodes.Ldloc_3; break; default: if (tempVal <= 255) { opcode = OpCodes.Ldloc_S; } break; } } else if (opcode.Equals(OpCodes.Stloc)) { switch (tempVal) { case 0: opcode = OpCodes.Stloc_0; break; case 1: opcode = OpCodes.Stloc_1; break; case 2: opcode = OpCodes.Stloc_2; break; case 3: opcode = OpCodes.Stloc_3; break; default: if (tempVal <= 255) { opcode = OpCodes.Stloc_S; } break; } } else if (opcode.Equals(OpCodes.Ldloca)) { if (tempVal <= 255) { opcode = OpCodes.Ldloca_S; } } AdvanceOffset(opcode); if (opcode.OperandType == OperandType.InlineNone) { return; } else if (!OpCodes.TakesSingleByteArgument(opcode)) { _offset += 2; } else { _offset++; } AssertOffsetMatches(); }
/// <summary> /// Constructor /// </summary> /// <param name="name">Local object name</param> /// <param name="localType">Local type</param> public DefineLocal(string name, Type localType) { Result = new LocalBuilder(MethodBase.CurrentMethod, name, localType); }
public VarInfo(LocalBuilder lb) { _lb = lb; _kind = VarKind.vkLocal; }
public virtual void EmitWriteLine(LocalBuilder localBuilder);
private static IEnumerable <CodeInstruction> Transpiler(IEnumerable <CodeInstruction> instructions, ILGenerator generator) { List <CodeInstruction> newInstructions = ListPool <CodeInstruction> .Shared.Rent(instructions); int offset = 0; int index = newInstructions.FindIndex(i => i.opcode == OpCodes.Ldarg_2) + offset; Label returnLabel = generator.DefineLabel(); Label setMaxHpLabel = generator.DefineLabel(); Label rpcLabel = generator.DefineLabel(); newInstructions[newInstructions.Count - 1].labels.Add(returnLabel); LocalBuilder ev = generator.DeclareLocal(typeof(InteractingShootingTargetEventArgs)); newInstructions.InsertRange(index, new[] { // Player.Get(ReferenceHub) new CodeInstruction(OpCodes.Ldarg_1).MoveLabelsFrom(newInstructions[index]), new CodeInstruction(OpCodes.Call, Method(typeof(Player), nameof(Player.Get), new[] { typeof(ReferenceHub) })), // this new CodeInstruction(OpCodes.Ldarg_0), // colliderId (ShootingTargetButton) new CodeInstruction(OpCodes.Ldarg_2), // GetNextValue(buttonPressed, ShootingTargetButton.DecreaseHp, BaseTarget._maxHp) new CodeInstruction(OpCodes.Ldarg_2), new CodeInstruction(OpCodes.Ldc_I4_1), new CodeInstruction(OpCodes.Ldarg_0), new CodeInstruction(OpCodes.Ldfld, Field(typeof(BaseTarget), nameof(BaseTarget._maxHp))), new CodeInstruction(OpCodes.Call, Method(typeof(InteractingShootingTarget), nameof(InteractingShootingTarget.GetNextValue))), // GetNextValue(buttonPressed, ShootingTargetButton.DecreaseResetTime, BaseTarget._autoDestroyTime) new CodeInstruction(OpCodes.Ldarg_2), new CodeInstruction(OpCodes.Ldc_I4_3), new CodeInstruction(OpCodes.Ldarg_0), new CodeInstruction(OpCodes.Ldfld, Field(typeof(BaseTarget), nameof(BaseTarget._autoDestroyTime))), new CodeInstruction(OpCodes.Call, Method(typeof(InteractingShootingTarget), nameof(InteractingShootingTarget.GetNextValue))), // true new CodeInstruction(OpCodes.Ldc_I4_1), // var ev = new InteractingShootingTargetEventArgs(Player, BaseTarget, ShootingTargetButton, MaxHp, ResetTime, true) new CodeInstruction(OpCodes.Newobj, GetDeclaredConstructors(typeof(InteractingShootingTargetEventArgs))[0]), new CodeInstruction(OpCodes.Dup), new CodeInstruction(OpCodes.Dup), new CodeInstruction(OpCodes.Stloc_S, ev.LocalIndex), // OnInteractingShootingTarget(ev) new CodeInstruction(OpCodes.Call, Method(typeof(Handlers.Player), nameof(Handlers.Player.OnInteractingShootingTarget))), // if (!ev.IsAllowed) // CheckMaxHp new CodeInstruction(OpCodes.Callvirt, PropertyGetter(typeof(InteractingShootingTargetEventArgs), nameof(InteractingShootingTargetEventArgs.IsAllowed))), new CodeInstruction(OpCodes.Brfalse, setMaxHpLabel), }); offset = 1; index = newInstructions.FindIndex(i => i.opcode == OpCodes.Call && (MethodInfo)i.operand == Method(typeof(NetworkServer), nameof(NetworkServer.Destroy))) + offset; newInstructions[index] = new CodeInstruction(OpCodes.Br, setMaxHpLabel); offset = 1; index = newInstructions.FindIndex(i => i.opcode == OpCodes.Call && (MethodInfo)i.operand == Method(typeof(BaseTarget), "set_Network_syncMode")) + offset; newInstructions[index] = new CodeInstruction(OpCodes.Br, setMaxHpLabel); offset = -5; index = newInstructions.FindIndex(i => i.opcode == OpCodes.Call && (MethodInfo)i.operand == Method(typeof(BaseTarget), nameof(BaseTarget.RpcSendInfo))) + offset; newInstructions[index].labels.Add(rpcLabel); newInstructions.InsertRange(index, new[] { // BaseTarget.MaxHp = ev.NewMaxHp new CodeInstruction(OpCodes.Ldarg_0).WithLabels(setMaxHpLabel), new CodeInstruction(OpCodes.Ldloc_S, ev.LocalIndex), new CodeInstruction(OpCodes.Callvirt, PropertyGetter(typeof(InteractingShootingTargetEventArgs), nameof(InteractingShootingTargetEventArgs.NewMaxHp))), new CodeInstruction(OpCodes.Stfld, Field(typeof(BaseTarget), nameof(BaseTarget._maxHp))), // BaseTarget._autoDestroyTime = ev.NewAutoResetTime new CodeInstruction(OpCodes.Ldarg_0), new CodeInstruction(OpCodes.Ldloc_S, ev.LocalIndex), new CodeInstruction(OpCodes.Callvirt, PropertyGetter(typeof(InteractingShootingTargetEventArgs), nameof(InteractingShootingTargetEventArgs.NewAutoResetTime))), new CodeInstruction(OpCodes.Stfld, Field(typeof(BaseTarget), nameof(BaseTarget._autoDestroyTime))), }); for (int z = 0; z < newInstructions.Count; z++) { yield return(newInstructions[z]); } ListPool <CodeInstruction> .Shared.Return(newInstructions); }
static void EmitPrepareArgStore(ILGenerator ilg, LocalBuilder bufLocal, int argnum) { EmitComputeBufferLoc(ilg, bufLocal, argnum); EmitLoadArg(ilg, argnum); }
public virtual void EmitWriteLine (LocalBuilder localBuilder) { throw new PlatformNotSupportedException (); }
internal FieldNullable(LocalBuilder stack, ILGenerator generator) : base(ToNullable(stack, generator), generator) { ValueInfo = typeof(Nullable <T>).GetProperty("Value").GetGetMethod(); HasValueInfo = typeof(Nullable <T>).GetProperty("HasValue").GetGetMethod(); GetValueOrDefaultInfo = typeof(Nullable <T>).GetMethod("GetValueOrDefault", Type.EmptyTypes); }
internal sealed override void Generate(CodeGenContext context, CodeEmitter ilgen) { Debug.Assert(Name != null); if(Name == ".ctor") { Debug.Assert(Class == null && type != null); Type[] argTypes = context.ClassLoader.ArgTypeListFromSig(Sig); ConstructorInfo ci = StaticCompiler.GetType(context.ClassLoader, type).GetConstructor(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance, null, CallingConventions.Standard, argTypes, null); if(ci == null) { throw new InvalidOperationException("Missing .ctor: " + type + "..ctor" + Sig); } ilgen.Emit(opcode, ci); } else { Debug.Assert(Class == null ^ type == null); if(Class != null) { Debug.Assert(Sig != null); MethodWrapper method = context.ClassLoader.LoadClassByDottedName(Class).GetMethodWrapper(Name, Sig, false); if(method == null) { throw new InvalidOperationException("method not found: " + Class + "." + Name + Sig); } method.Link(); // TODO this code is part of what Compiler.CastInterfaceArgs (in compiler.cs) does, // it would be nice if we could avoid this duplication... TypeWrapper[] argTypeWrappers = method.GetParameters(); for(int i = 0; i < argTypeWrappers.Length; i++) { if(argTypeWrappers[i].IsGhost) { LocalBuilder[] temps = new LocalBuilder[argTypeWrappers.Length + (method.IsStatic ? 0 : 1)]; for(int j = temps.Length - 1; j >= 0; j--) { TypeWrapper tw; if(method.IsStatic) { tw = argTypeWrappers[j]; } else { if(j == 0) { tw = method.DeclaringType; } else { tw = argTypeWrappers[j - 1]; } } if(tw.IsGhost) { tw.EmitConvStackTypeToSignatureType(ilgen, null); } temps[j] = ilgen.DeclareLocal(tw.TypeAsSignatureType); ilgen.Emit(OpCodes.Stloc, temps[j]); } for(int j = 0; j < temps.Length; j++) { ilgen.Emit(OpCodes.Ldloc, temps[j]); } break; } } if(opcode.Value == OpCodes.Call.Value) { method.EmitCall(ilgen); } else if(opcode.Value == OpCodes.Callvirt.Value) { method.EmitCallvirt(ilgen); } else if(opcode.Value == OpCodes.Newobj.Value) { method.EmitNewobj(ilgen); } else { throw new InvalidOperationException(); } } else { Type[] argTypes; if(Sig.StartsWith("(")) { argTypes = context.ClassLoader.ArgTypeListFromSig(Sig); } else { string[] types = Sig.Split(';'); argTypes = new Type[types.Length]; for(int i = 0; i < types.Length; i++) { argTypes[i] = StaticCompiler.GetType(context.ClassLoader, types[i]); } } MethodInfo mi = StaticCompiler.GetType(context.ClassLoader, type).GetMethod(Name, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static, null, argTypes, null); if(mi == null) { throw new InvalidOperationException("Missing method: " + type + "." + Name + Sig); } ilgen.Emit(opcode, mi); } } }
private static DynamicMethod CreateClassDeserializerDynamicMethod(Type type, IDataReader reader, IRecordStructure structure, int startColumn, int columnCount, bool createNewObject, bool isRootObject, bool allowBindChild, bool checkForAllDbNull) { // if there are no columns detected for the class, then don't deserialize it // exception: a parentandchild object in the middle of a child hierarchy var genericType = type.GetTypeInfo().IsGenericType ? type.GetGenericTypeDefinition() : null; if (columnCount == 0 && !isRootObject && genericType != typeof(ParentAndChild <,>)) { return(null); } var mappings = MapColumns(type, reader, startColumn, columnCount, structure, allowBindChild && isRootObject); // need to know the constructor for the object (except for structs) bool isStruct = type.GetTypeInfo().IsValueType; ConstructorInfo constructor = createNewObject ? SelectConstructor(type) : null; // if there is a constructor, determine which columns will be mapped to constructor parameters // constructorMappings will be indexes into the mappin array (or -1 if there is no mapping) var constructorParameters = (constructor != null) ? constructor.GetParameters() : null; var constructorMappings = (constructor != null) ? constructorParameters.Select(p => mappings.FindIndex(m => m != null && p.Name.IsIEqualTo(m.Member.Name))).ToArray() : new int[0]; // remove any mappings that are not settable and not used for constructor initialization // this will save on translating properties we can't set and prevent issue #459 for (var m = 0; m < mappings.Count; m++) { if (mappings[m] != null && !mappings[m].Member.CanSetMember && !constructorMappings.Contains(m)) { mappings[m] = null; } } // the method can either be: // createNewObject => Func<IDataReader, T> // !createNewObject => Func<IDataReader, T, T> // create a new anonymous method that takes an IDataReader and returns the given type var dm = new DynamicMethod( String.Format(CultureInfo.InvariantCulture, "Deserialize-{0}-{1}", type.FullName, Guid.NewGuid()), type, createNewObject ? new[] { typeof(IDataReader) } : new[] { typeof(IDataReader), type }, true); // get the il generator and put some local variables on the stack var il = dm.GetILGenerator(); var localIndex = il.DeclareLocal(typeof(int)); var localResult = il.DeclareLocal(type); var localValue = il.DeclareLocal(typeof(object)); var localIsNotAllDbNull = il.DeclareLocal(typeof(bool)); // initialization il.Emit(OpCodes.Ldc_I4_0); il.Emit(OpCodes.Stloc, localIndex); ///////////////////////////////////////////////////////////////////// // read all of the values into local variables ///////////////////////////////////////////////////////////////////// il.BeginExceptionBlock(); var hasAtLeastOneMapping = false; var localValues = new LocalBuilder[mappings.Count]; for (int index = 0; index < columnCount; index++) { var mapping = mappings[index]; if (mapping == null) { continue; } hasAtLeastOneMapping = true; var member = mapping.Member; localValues[index] = il.DeclareLocal(member.MemberType); // need to call IDataReader.GetItem to get the value of the field il.Emit(OpCodes.Ldarg_0); IlHelper.EmitLdInt32(il, index + startColumn); // before we call it, put the current index into the index local variable il.Emit(OpCodes.Dup); il.Emit(OpCodes.Stloc, localIndex); // now call it il.Emit(OpCodes.Callvirt, _iDataReaderGetItem); // if handling a subobject, we check to see if the value is null if (startColumn > 0) { var afterNullCheck = il.DefineLabel(); il.Emit(OpCodes.Dup); il.Emit(OpCodes.Ldsfld, typeof(DBNull).GetField("Value")); il.Emit(OpCodes.Ceq); il.Emit(OpCodes.Brtrue, afterNullCheck); il.Emit(OpCodes.Ldc_I4_1); il.Emit(OpCodes.Stloc, localIsNotAllDbNull); il.MarkLabel(afterNullCheck); } // store the value as a local variable in case type conversion fails il.Emit(OpCodes.Dup); il.Emit(OpCodes.Stloc, localValue); // convert the value and store it locally Type sourceType = reader.GetFieldType(index + startColumn); TypeConverterGenerator.EmitConvertValue(il, member.Name, sourceType, member.MemberType, mapping.Serializer); il.Emit(OpCodes.Stloc, localValues[index]); } ///////////////////////////////////////////////////////////////////// // catch translation exceptions and rethrow ///////////////////////////////////////////////////////////////////// il.BeginCatchBlock(typeof(Exception)); // stack => [Exception] il.Emit(OpCodes.Ldloc, localIndex); // push loc.0, stack => [Exception][index] il.Emit(OpCodes.Ldarg_0); // push arg.0, stack => [Exception][index][reader] il.Emit(OpCodes.Ldloc, localValue); // push loc.3, stack => [Exception][index][reader][value] il.Emit(OpCodes.Call, TypeConverterGenerator.CreateDataExceptionMethod); il.Emit(OpCodes.Throw); // stack => DataException il.EndExceptionBlock(); ///////////////////////////////////////////////////////////////////// // if this was a subobject and all of the values are null, then return the default for the object ///////////////////////////////////////////////////////////////////// if (hasAtLeastOneMapping && checkForAllDbNull) { var afterNullExit = il.DefineLabel(); il.Emit(OpCodes.Ldloc, localIsNotAllDbNull); il.Emit(OpCodes.Brtrue, afterNullExit); TypeHelper.EmitDefaultValue(il, type); il.Emit(OpCodes.Ret); il.MarkLabel(afterNullExit); } ///////////////////////////////////////////////////////////////////// // call the constructor ///////////////////////////////////////////////////////////////////// if (createNewObject) { if (isStruct) { il.Emit(OpCodes.Ldloca_S, localResult); il.Emit(OpCodes.Initobj, type); if (constructor != null) { il.Emit(OpCodes.Ldloca_S, localResult); } } // if there is a constructor, then populate the values from the pre-converted local values we created above if (constructor != null) { for (var p = 0; p < constructorParameters.Length; p++) { if (constructorMappings[p] >= 0) { il.Emit(OpCodes.Ldloc, localValues[constructorMappings[p]]); } else { TypeHelper.EmitDefaultValue(il, constructorParameters[p].ParameterType); } } } if (isStruct) { if (constructor != null) { il.Emit(OpCodes.Call, constructor); } } else { il.Emit(OpCodes.Newobj, constructor); il.Emit(OpCodes.Stloc, localResult); } } else { il.Emit(OpCodes.Ldarg_1); il.Emit(OpCodes.Stloc, localResult); } ///////////////////////////////////////////////////////////////////// // for anything not passed to the constructor, copy the local values to the properties ///////////////////////////////////////////////////////////////////// for (int index = 0; index < columnCount; index++) { var mapping = mappings[index]; if (mapping == null) { continue; } // don't attempt to set values that can't be set at all var member = mapping.Member; if (!member.CanSetMember) { continue; } // don't set values that have already been set in the constructor if (constructorMappings.Contains(index)) { continue; } // load the address of the object we are working on if (isStruct) { il.Emit(OpCodes.Ldloca_S, localResult); } else { il.Emit(OpCodes.Ldloc, localResult); } // for deep mappings, go to the parent of the field that we are trying to set var nextLabel = il.DefineLabel(); if (mapping.IsDeep) { ClassPropInfo.EmitGetValue(type, mapping.Prefix, il); // if the mapping parent is nullable, check to see if it is null. // if so, pop the parent off the stack and move to the next field if (!ClassPropInfo.FindMember(type, mapping.Prefix).MemberType.GetTypeInfo().IsValueType) { var notNullLabel = il.DefineLabel(); il.Emit(OpCodes.Dup); il.Emit(OpCodes.Brtrue, notNullLabel); il.Emit(OpCodes.Pop); il.Emit(OpCodes.Br, nextLabel); il.MarkLabel(notNullLabel); } } // load the value from the local and set it on the object il.Emit(OpCodes.Ldloc, localValues[index]); member.EmitSetValue(il); il.MarkLabel(nextLabel); ///////////////////////////////////////////////////////////////////// // stack should be [target] and ready for the next column ///////////////////////////////////////////////////////////////////// } ///////////////////////////////////////////////////////////////////// // load the return value from the local variable ///////////////////////////////////////////////////////////////////// il.Emit(OpCodes.Ldloc, localResult); // ld loc.1 (target), stack => [target] il.Emit(OpCodes.Ret); // create the function return(dm); }
static void EmitLoadReturnSlot_1(ILGenerator ilg, LocalBuilder bufLocal, int slotnum) { ilg.Emit(OpCodes.Ldloc, bufLocal); ilg.Emit(OpCodes.Ldc_I4, (slotnum - 1) * VARIANT_SIZE); ilg.Emit(OpCodes.Add); ilg.Emit(OpCodes.Ldind_I4); }
/// <summary> /// 创建 TCP 客户端 /// </summary> /// <param name="type"></param> /// <param name="attribute"></param> /// <param name="methods"></param> /// <param name="getCommandMethod"></param> /// <returns></returns> internal Type Build(Type type, ServerBaseAttribute attribute, Method <attributeType, methodAttributeType, serverSocketSenderType>[] methods, MethodInfo getCommandMethod) { TypeBuilder typeBuilder = AutoCSer.Emit.Builder.Module.Builder.DefineType(Metadata.ClientTypeName + ".Emit." + type.FullName, TypeAttributes.Class | TypeAttributes.Sealed, Metadata.MethodClientType, new Type[] { type }); typeBuilder.DefineDefaultConstructor(MethodAttributes.Public); ConstructorBuilder staticConstructorBuilder = typeBuilder.DefineConstructor(MethodAttributes.Public | MethodAttributes.Static, CallingConventions.Standard, null); ILGenerator staticConstructorGenerator = staticConstructorBuilder.GetILGenerator(); Commands = new CommandInfo[methods.Length]; int parameterIndex; foreach (Method <attributeType, methodAttributeType, serverSocketSenderType> nextMethod in methods) { if (nextMethod != null) { Method <attributeType, methodAttributeType, serverSocketSenderType> method = nextMethod; METHOD: FieldBuilder commandInfoFieldBuilder; if (method.Attribute.IsExpired) { commandInfoFieldBuilder = null; } else { commandInfoFieldBuilder = typeBuilder.DefineField("_c" + method.Attribute.CommandIdentity.toString(), typeof(CommandInfo), FieldAttributes.Private | FieldAttributes.InitOnly | FieldAttributes.Static); CommandInfo commandInfo = new CommandInfo { Command = method.Attribute.CommandIdentity + TcpServer.Server.CommandStartIndex, TaskType = method.IsAsynchronousCallback ? method.Attribute.ClientTaskType : AutoCSer.Net.TcpServer.ClientTaskType.Synchronous, IsVerifyMethod = method.Attribute.IsVerifyMethod }; Commands[method.Attribute.CommandIdentity] = commandInfo; if (method.IsClientSendOnly) { commandInfo.IsSendOnly = 1; } if (method.IsJsonSerialize) { commandInfo.CommandFlags = CommandFlags.JsonSerialize; } if (method.ParameterType != null) { commandInfo.InputParameterIndex = method.ParameterType.Index; if (attribute.IsSimpleSerialize) { commandInfo.IsSimpleSerializeInputParamter = method.ParameterType.IsSimpleSerialize; } } if (attribute.IsSimpleSerialize && method.OutputParameterType != null) { commandInfo.IsSimpleSerializeOutputParamter = method.OutputParameterType.IsSimpleSerialize && SimpleSerialize.Serializer.IsType(method.ReturnType); } #region private static readonly AutoCSer.Net.TcpServer.CommandInfo @MethodIdentityCommand = AutoCSer.Net.TcpInternalServer.Emit.Client<interfaceType>.commands[method.Attribute.CommandIdentity]; staticConstructorGenerator.int32(method.Attribute.CommandIdentity); staticConstructorGenerator.call(getCommandMethod); staticConstructorGenerator.Emit(OpCodes.Stsfld, commandInfoFieldBuilder); #endregion } if (method.PropertyInfo == null) { ParameterInfo[] parameters = method.MethodInfo.GetParameters(); MethodBuilder methodBuilder = typeBuilder.DefineMethod(method.MethodInfo.Name, MethodAttributes.Private | MethodAttributes.HideBySig | MethodAttributes.NewSlot | MethodAttributes.Virtual | MethodAttributes.Final, method.MethodInfo.ReturnType, parameters.getArray(parameter => parameter.ParameterType)); typeBuilder.DefineMethodOverride(methodBuilder, method.MethodInfo); ILGenerator methodGenerator = methodBuilder.GetILGenerator(); if (method.Attribute.IsExpired) { if (method.ReturnValueType == null) { #region throw new Exception(AutoCSer.Net.TcpServer.ReturnType.VersionExpired.ToString()); methodGenerator.throwString(AutoCSer.Net.TcpServer.ReturnType.VersionExpired.ToString()); #endregion } else { #region @ParameterName = default(@ParameterType.FullName); parameterIndex = 0; foreach (ParameterInfo parameter in parameters) { ++parameterIndex; if (parameter.IsOut) { methodGenerator.outParameterDefault(parameter, parameterIndex, method.Attribute.IsInitobj); } } #endregion #region return new AutoCSer.Net.TcpServer.ReturnValue<@MethodReturnType.FullName> { Type = AutoCSer.Net.TcpServer.ReturnType.VersionExpired }; LocalBuilder returnReturnValueLocalBuilder = methodGenerator.DeclareLocal(method.ReturnValueType); if (method.ReturnType != typeof(void) && (method.Attribute.IsInitobj || method.ReturnType.isInitobj())) { methodGenerator.Emit(OpCodes.Ldloca_S, returnReturnValueLocalBuilder); methodGenerator.Emit(OpCodes.Initobj, method.ReturnValueType); } methodGenerator.Emit(OpCodes.Ldloca_S, returnReturnValueLocalBuilder); methodGenerator.int32((byte)AutoCSer.Net.TcpServer.ReturnType.VersionExpired); methodGenerator.Emit(OpCodes.Stfld, method.ReturnType == typeof(void) ? TcpServer.Emit.ClientMetadata.ReturnValueTypeField : method.ReturnValueType.GetField(TcpServer.Emit.ClientMetadata.ReturnValueTypeField.Name, BindingFlags.Instance | BindingFlags.Public)); methodGenerator.Emit(OpCodes.Ldloc_S, returnReturnValueLocalBuilder); methodGenerator.Emit(OpCodes.Ret); #endregion } } else if (method.IsClientSendOnly) { LocalBuilder inputParameterLocalBuilder; if (method.ParameterType == null) { inputParameterLocalBuilder = null; } else { #region TcpInternalServer.@InputParameterTypeName _inputParameter_ = new TcpInternalServer.@InputParameterTypeName { @ParameterName = @ParameterName }; inputParameterLocalBuilder = methodGenerator.DeclareLocal(method.ParameterType.Type); LocalBuilder newInputParameterLocalBuilder = methodGenerator.DeclareLocal(method.ParameterType.Type); if (method.Attribute.IsInitobj || method.ParameterType.IsInitobj) { methodGenerator.Emit(OpCodes.Ldloca_S, newInputParameterLocalBuilder); methodGenerator.Emit(OpCodes.Initobj, method.ParameterType.Type); } parameterIndex = 0; foreach (ParameterInfo parameter in parameters) { ++parameterIndex; if (StreamParameterType.IsInputParameter(parameter)) { methodGenerator.parameterToStructField(parameter, parameterIndex, newInputParameterLocalBuilder, method.ParameterType.GetField(parameter.Name)); } } methodGenerator.Emit(OpCodes.Ldloc_S, newInputParameterLocalBuilder); methodGenerator.Emit(OpCodes.Stloc_S, inputParameterLocalBuilder); #endregion } #region _TcpClient_.Sender.CallOnly(@MethodIdentityCommand, ref _inputParameter_); methodGenerator.Emit(OpCodes.Ldarg_0); methodGenerator.call(Metadata.MethodClientGetTcpClientMethod); methodGenerator.call(Metadata.ClientGetSenderMethod); methodGenerator.Emit(OpCodes.Ldsfld, commandInfoFieldBuilder); if (method.ParameterType == null) { methodGenerator.call(Metadata.ClientSocketSenderCallOnlyMethod); } else { methodGenerator.Emit(OpCodes.Ldloca_S, inputParameterLocalBuilder); methodGenerator.call(Metadata.ClientSocketSenderCallOnlyInputMethod.MakeGenericMethod(method.ParameterType.Type)); } #endregion methodGenerator.Emit(OpCodes.Ret); } else { Label clientExceptionLabel = methodGenerator.DefineLabel(), returnLable = methodGenerator.DefineLabel(), returnReturnValueLable, returnValueLable; LocalBuilder returnReturnValueLocalBuilder, returnValueLocalBuilder; if (method.ReturnValueType == null) { returnReturnValueLocalBuilder = null; returnReturnValueLable = default(Label); } else { returnReturnValueLocalBuilder = methodGenerator.DeclareLocal(method.ReturnValueType); returnReturnValueLable = methodGenerator.DefineLabel(); } if (method.ReturnValueType == null && method.ReturnType != typeof(void)) { returnValueLocalBuilder = methodGenerator.DeclareLocal(method.ReturnType); returnValueLable = methodGenerator.DefineLabel(); } else { returnValueLocalBuilder = null; returnValueLable = default(Label); } #region AutoCSer.Net.TcpServer.AutoWaitReturnValue<TcpInternalServer.@OutputParameterTypeName> _wait_ = _TcpClient_.GetAutoWait<TcpInternalServer.@OutputParameterTypeName>(); Type waitType = method.OutputParameterType == null ? typeof(AutoCSer.Net.TcpServer.AutoWaitReturnValue) : typeof(AutoCSer.Net.TcpServer.AutoWaitReturnValue <>).MakeGenericType(method.OutputParameterType.Type); LocalBuilder waitLocalBuilder = methodGenerator.DeclareLocal(waitType); methodGenerator.call(method.OutputParameterType == null ? TcpServer.Emit.ClientMetadata.AutoWaitReturnValuePopMethod : waitType.GetMethod("Pop", BindingFlags.Static | BindingFlags.Public)); methodGenerator.Emit(OpCodes.Stloc_S, waitLocalBuilder); #endregion #region try methodGenerator.BeginExceptionBlock(); #endregion Label leaveTryLabel = methodGenerator.DefineLabel(); LocalBuilder senderLocalBuilder = methodGenerator.DeclareLocal(Metadata.SenderType); parameterIndex = 0; if (method.Attribute.IsVerifyMethod) { foreach (ParameterInfo parameter in parameters) { ++parameterIndex; if (parameter.ParameterType == Metadata.SenderType) { #region AutoCSer.Net.TcpInternalServer.ClientSocketSender _socket_ = _sender_; methodGenerator.ldarg(parameterIndex); methodGenerator.Emit(OpCodes.Stloc_S, senderLocalBuilder); #endregion parameterIndex = int.MinValue; break; } } } if (parameterIndex != int.MinValue) { #region AutoCSer.Net.TcpInternalServer.ClientSocketSender _socket_ = _TcpClient_.Sender; methodGenerator.Emit(OpCodes.Ldarg_0); methodGenerator.call(Metadata.MethodClientGetTcpClientMethod); methodGenerator.call(Metadata.ClientGetSenderMethod); methodGenerator.Emit(OpCodes.Stloc_S, senderLocalBuilder); #endregion } #region if (_socket_ != null) methodGenerator.Emit(OpCodes.Ldloc_S, senderLocalBuilder); methodGenerator.Emit(method.ParameterType == null ? OpCodes.Brfalse_S : OpCodes.Brfalse, leaveTryLabel); #endregion LocalBuilder inputParameterLocalBuilder; if (method.ParameterType == null) { inputParameterLocalBuilder = null; } else { #region TcpInternalServer.@InputParameterTypeName _inputParameter_ = new TcpInternalServer.@InputParameterTypeName { @ParameterName = @ParameterName }; inputParameterLocalBuilder = methodGenerator.DeclareLocal(method.ParameterType.Type); LocalBuilder newInputParameterLocalBuilder = methodGenerator.DeclareLocal(method.ParameterType.Type); if (method.Attribute.IsInitobj || method.ParameterType.IsInitobj) { methodGenerator.Emit(OpCodes.Ldloca_S, newInputParameterLocalBuilder); methodGenerator.Emit(OpCodes.Initobj, method.ParameterType.Type); } parameterIndex = 0; foreach (ParameterInfo parameter in parameters) { ++parameterIndex; if (StreamParameterType.IsInputParameter(parameter)) { methodGenerator.parameterToStructField(parameter, parameterIndex, newInputParameterLocalBuilder, method.ParameterType.GetField(parameter.Name)); } } methodGenerator.Emit(OpCodes.Ldloc_S, newInputParameterLocalBuilder); methodGenerator.Emit(OpCodes.Stloc_S, inputParameterLocalBuilder); #endregion } if (method.OutputParameterType == null) { #region AutoCSer.Net.TcpServer.ReturnType _returnType_ = _socket_.WaitCall(@MethodIdentityCommand, ref _wait_, ref _inputParameter_); LocalBuilder returnTypeLocalBuilder = methodGenerator.DeclareLocal(typeof(AutoCSer.Net.TcpServer.ReturnType)); methodGenerator.Emit(OpCodes.Ldloc_S, senderLocalBuilder); methodGenerator.Emit(OpCodes.Ldsfld, commandInfoFieldBuilder); methodGenerator.Emit(OpCodes.Ldloca_S, waitLocalBuilder); if (method.ParameterType == null) { methodGenerator.call(Metadata.ClientSocketSenderWaitCallMethod); } else { methodGenerator.Emit(OpCodes.Ldloca_S, inputParameterLocalBuilder); methodGenerator.call(Metadata.ClientSocketSenderWaitCallInputMethod.MakeGenericMethod(method.ParameterType.Type)); } methodGenerator.Emit(OpCodes.Stloc_S, returnTypeLocalBuilder); #endregion if (method.ReturnValueType == null) { Label throwReturnTypeLabel = methodGenerator.DefineLabel(); #region if (_returnType_ == AutoCSer.Net.TcpServer.ReturnType.Success) return; methodGenerator.Emit(OpCodes.Ldloc_S, returnTypeLocalBuilder); methodGenerator.int32((byte)AutoCSer.Net.TcpServer.ReturnType.Success); methodGenerator.Emit(OpCodes.Bne_Un_S, throwReturnTypeLabel); methodGenerator.Emit(OpCodes.Leave_S, returnLable); #endregion methodGenerator.MarkLabel(throwReturnTypeLabel); #region throw new Exception(AutoCSer.Net.TcpInternalServer.Emit.Client.ReturnTypeStrings[(byte)_returnType_]); methodGenerator.Emit(OpCodes.Ldsfld, TcpServer.Emit.ClientMetadata.ReturnTypeStringsField); methodGenerator.Emit(OpCodes.Ldloc_S, returnTypeLocalBuilder); methodGenerator.Emit(OpCodes.Ldelem_Ref); methodGenerator.Emit(OpCodes.Newobj, AutoCSer.Extension.EmitGenerator.StringExceptionConstructor); methodGenerator.Emit(OpCodes.Throw); #endregion } else { #region return new AutoCSer.Net.TcpServer.ReturnValue { Type = _returnType_ }; //methodGenerator.Emit(OpCodes.Ldloca_S, returnReturnValueLocalBuilder); //methodGenerator.Emit(OpCodes.Initobj, method.ReturnValueType); methodGenerator.Emit(OpCodes.Ldloca_S, returnReturnValueLocalBuilder); methodGenerator.Emit(OpCodes.Ldloc_S, returnTypeLocalBuilder); methodGenerator.Emit(OpCodes.Stfld, TcpServer.Emit.ClientMetadata.ReturnValueTypeField); methodGenerator.Emit(OpCodes.Leave, returnReturnValueLable); #endregion } } else { #region TcpInternalServer.@OutputParameterTypeName _outputParameter_ = new TcpInternalServer.@OutputParameterTypeName { @ParameterName = @ParameterName }; LocalBuilder 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); } parameterIndex = 0; foreach (ParameterInfo parameter in parameters) { ++parameterIndex; if (parameter.ParameterType.IsByRef) { methodGenerator.parameterToStructField(parameter, parameterIndex, outputParameterLocalBuilder, method.OutputParameterType.GetField(parameter.Name)); } } //if (method.ReturnInputParameter != null) //{ //} #endregion #region AutoCSer.Net.TcpServer.ReturnType _returnType_ = _socket_.WaitGet<TcpInternalServer.@InputParameterTypeName, TcpInternalServer.@OutputParameterTypeName>(@MethodIdentityCommand, ref _wait_, ref _inputParameter_, ref _outputParameter_); LocalBuilder returnTypeLocalBuilder = methodGenerator.DeclareLocal(typeof(AutoCSer.Net.TcpServer.ReturnType)); methodGenerator.Emit(OpCodes.Ldloc_S, senderLocalBuilder); methodGenerator.Emit(OpCodes.Ldsfld, commandInfoFieldBuilder); methodGenerator.Emit(OpCodes.Ldloca_S, waitLocalBuilder); if (method.ParameterType == null) { methodGenerator.Emit(OpCodes.Ldloca_S, outputParameterLocalBuilder); methodGenerator.call(Metadata.ClientSocketSenderWaitGetMethod.MakeGenericMethod(method.OutputParameterType.Type)); } else { methodGenerator.Emit(OpCodes.Ldloca_S, inputParameterLocalBuilder); methodGenerator.Emit(OpCodes.Ldloca_S, outputParameterLocalBuilder); methodGenerator.call(Metadata.ClientSocketSenderWaitGetInputMethod.MakeGenericMethod(method.ParameterType.Type, method.OutputParameterType.Type)); } methodGenerator.Emit(OpCodes.Stloc_S, returnTypeLocalBuilder); #endregion if (method.ReturnValueType == null) { Label throwReturnTypeLabel = methodGenerator.DefineLabel(); #region if (_returnType_ == AutoCSer.Net.TcpServer.ReturnType.Success) methodGenerator.Emit(OpCodes.Ldloc_S, returnTypeLocalBuilder); methodGenerator.int32((byte)AutoCSer.Net.TcpServer.ReturnType.Success); methodGenerator.Emit(OpCodes.Bne_Un, throwReturnTypeLabel); #endregion #region @ParameterName = _outputParameter_.@ParameterName; parameterIndex = 0; foreach (ParameterInfo parameter in parameters) { ++parameterIndex; if (parameter.ParameterType.IsByRef) { methodGenerator.outParameterFromValueField(parameter, parameterIndex, outputParameterLocalBuilder, method.OutputParameterType.GetField(parameter.Name)); } } #endregion if (method.ReturnType == typeof(void)) { #region return; methodGenerator.Emit(OpCodes.Leave_S, returnLable); #endregion } else { #region return _outputParameter_.Ret; methodGenerator.Emit(OpCodes.Ldloca_S, outputParameterLocalBuilder); methodGenerator.Emit(OpCodes.Ldfld, method.OutputParameterType.GetField(TcpServer.ReturnValue.RetParameterName)); methodGenerator.Emit(OpCodes.Stloc_S, returnValueLocalBuilder); methodGenerator.Emit(OpCodes.Leave_S, returnValueLable); #endregion } methodGenerator.MarkLabel(throwReturnTypeLabel); #region throw new Exception(AutoCSer.Net.TcpServer.Emit.Client.ReturnTypeStrings[(byte)_returnType_]); methodGenerator.Emit(OpCodes.Ldsfld, TcpServer.Emit.ClientMetadata.ReturnTypeStringsField); methodGenerator.Emit(OpCodes.Ldloc_S, returnTypeLocalBuilder); methodGenerator.Emit(OpCodes.Ldelem_Ref); methodGenerator.Emit(OpCodes.Newobj, AutoCSer.Extension.EmitGenerator.StringExceptionConstructor); methodGenerator.Emit(OpCodes.Throw); #endregion } else { #region @ParameterName = _outputParameter_.@ParameterName; parameterIndex = 0; foreach (ParameterInfo parameter in parameters) { ++parameterIndex; if (parameter.ParameterType.IsByRef) { methodGenerator.outParameterFromValueField(parameter, parameterIndex, outputParameterLocalBuilder, method.OutputParameterType.GetField(parameter.Name)); } } #endregion #region return new AutoCSer.Net.TcpServer.ReturnValue<@MethodReturnType.FullName> { Type = _returnType_, Value = _outputParameter_.Return }; if (method.ReturnType != typeof(void) && (method.Attribute.IsInitobj || method.ReturnType.isInitobj())) { methodGenerator.Emit(OpCodes.Ldloca_S, returnReturnValueLocalBuilder); methodGenerator.Emit(OpCodes.Initobj, method.ReturnValueType); } methodGenerator.Emit(OpCodes.Ldloca_S, returnReturnValueLocalBuilder); methodGenerator.Emit(OpCodes.Ldloc_S, returnTypeLocalBuilder); methodGenerator.Emit(OpCodes.Stfld, method.ReturnType == typeof(void) ? TcpServer.Emit.ClientMetadata.ReturnValueTypeField : method.ReturnValueType.GetField(TcpServer.Emit.ClientMetadata.ReturnValueTypeField.Name, BindingFlags.Instance | BindingFlags.Public)); if (method.ReturnType != typeof(void)) { methodGenerator.Emit(OpCodes.Ldloca_S, returnReturnValueLocalBuilder); methodGenerator.Emit(OpCodes.Ldloca_S, outputParameterLocalBuilder); methodGenerator.Emit(OpCodes.Ldfld, method.OutputParameterType.GetField(ReturnValue.RetParameterName)); methodGenerator.Emit(OpCodes.Stfld, method.ReturnValueType.GetField("Value", BindingFlags.Instance | BindingFlags.Public)); } methodGenerator.Emit(OpCodes.Leave, returnReturnValueLable); #endregion } } methodGenerator.MarkLabel(leaveTryLabel); methodGenerator.Emit(OpCodes.Leave_S, clientExceptionLabel); #region finally methodGenerator.BeginFinallyBlock(); #endregion Label endfinallyLabel = methodGenerator.DefineLabel(); #region if (_wait_ != null) methodGenerator.Emit(OpCodes.Ldloc_S, waitLocalBuilder); methodGenerator.Emit(OpCodes.Brfalse_S, endfinallyLabel); #endregion #region AutoCSer.Net.TcpServer.AutoWaitReturnValue<TcpInternalServer.@OutputParameterTypeName>.PushNotNull(_wait_); methodGenerator.Emit(OpCodes.Ldloc_S, waitLocalBuilder); if (method.OutputParameterType == null) { methodGenerator.call(TcpServer.Emit.ClientMetadata.AutoWaitReturnValuePushNotNullMethod); } else { Type autoWaitReturnValueType = typeof(AutoCSer.Net.TcpServer.AutoWaitReturnValue <>).MakeGenericType(method.OutputParameterType.Type); methodGenerator.call(autoWaitReturnValueType.GetMethod(TcpServer.Emit.ClientMetadata.AutoWaitReturnValuePushNotNullMethod.Name, BindingFlags.Static | BindingFlags.Public, null, new Type[] { autoWaitReturnValueType }, null)); } #endregion methodGenerator.MarkLabel(endfinallyLabel); methodGenerator.Emit(OpCodes.Endfinally); #region try end methodGenerator.EndExceptionBlock(); #endregion methodGenerator.MarkLabel(clientExceptionLabel); if (method.ReturnValueType == null) { #region throw new Exception(AutoCSer.Net.TcpServer.ReturnType.ClientException.ToString()); methodGenerator.throwString(AutoCSer.Net.TcpServer.ReturnType.ClientException.ToString()); #endregion methodGenerator.MarkLabel(returnLable); methodGenerator.Emit(OpCodes.Ret); if (method.ReturnType != typeof(void)) { methodGenerator.MarkLabel(returnValueLable); #region @MethodReturnType.FullName methodGenerator.Emit(OpCodes.Ldloc_S, returnValueLocalBuilder); methodGenerator.Emit(OpCodes.Ret); #endregion } } else { #region @ParameterName = default(@ParameterType.FullName); parameterIndex = 0; foreach (ParameterInfo parameter in parameters) { ++parameterIndex; if (parameter.IsOut) { methodGenerator.outParameterDefault(parameter, parameterIndex, method.Attribute.IsInitobj); } } #endregion #region return new AutoCSer.Net.TcpServer.ReturnValue<@MethodReturnType.FullName> { Type = AutoCSer.Net.TcpServer.ReturnType.ClientException }; if (method.ReturnType != typeof(void) && (method.Attribute.IsInitobj || method.ReturnType.isInitobj())) { methodGenerator.Emit(OpCodes.Ldloca_S, returnReturnValueLocalBuilder); methodGenerator.Emit(OpCodes.Initobj, method.ReturnValueType); } methodGenerator.Emit(OpCodes.Ldloca_S, returnReturnValueLocalBuilder); methodGenerator.int32((byte)AutoCSer.Net.TcpServer.ReturnType.ClientException); methodGenerator.Emit(OpCodes.Stfld, method.ReturnType == typeof(void) ? TcpServer.Emit.ClientMetadata.ReturnValueTypeField : method.ReturnValueType.GetField(TcpServer.Emit.ClientMetadata.ReturnValueTypeField.Name, BindingFlags.Instance | BindingFlags.Public)); methodGenerator.MarkLabel(returnReturnValueLable); methodGenerator.Emit(OpCodes.Ldloc_S, returnReturnValueLocalBuilder); methodGenerator.MarkLabel(returnLable); methodGenerator.Emit(OpCodes.Ret); #endregion } } } else if (method.IsPropertySetMethod) { if (method.PropertyBuilder != null || method.PropertyGetMethod == null) { ParameterInfo[] parameters = method.MethodInfo.GetParameters(); PropertyBuilder propertyBuilder = method.PropertyBuilder ?? typeBuilder.DefineProperty(method.PropertyInfo.Name, PropertyAttributes.HasDefault, parameters[parameters.Length - 1].ParameterType, new LeftArray <ParameterInfo> { Array = parameters, Length = parameters.Length - 1 }.GetArray(parameter => parameter.ParameterType)); MethodBuilder setMethodBuilder = typeBuilder.DefineMethod(method.MethodInfo.Name, MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.HideBySig | MethodAttributes.Virtual, method.MethodInfo.ReturnType, parameters.getArray(parameter => parameter.ParameterType)); ILGenerator methodGenerator = setMethodBuilder.GetILGenerator(); //XXX propertyBuilder.SetSetMethod(setMethodBuilder); method.PropertyBuilder = null; } } else { Type[] parameterTypes = method.MethodInfo.GetParameters().getArray(parameter => parameter.ParameterType); PropertyBuilder propertyBuilder = typeBuilder.DefineProperty(method.PropertyInfo.Name, PropertyAttributes.HasDefault, method.MethodInfo.ReturnType, parameterTypes); MethodBuilder getMethodBuilder = typeBuilder.DefineMethod(method.MethodInfo.Name, MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.HideBySig | MethodAttributes.Virtual, method.MethodInfo.ReturnType, parameterTypes); ILGenerator methodGenerator = getMethodBuilder.GetILGenerator(); //XXX propertyBuilder.SetGetMethod(getMethodBuilder); if (method.PropertySetMethod != null) { method = method.PropertySetMethod; method.PropertyBuilder = propertyBuilder; goto METHOD; } } } } staticConstructorGenerator.Emit(OpCodes.Ret); return(typeBuilder.CreateType()); }
private EmitHelper InitGeneralPropertyInfo(EmitHelper emiter, LocalBuilder local, IProperty property) { var propertyType = property.GetType(); var mapType = typeof(PropertyMapInfo); emiter = emiter .ldtoken(EntityType).call(MethodCache.TypeGetTypeFromHandle) .newobj(propertyType) .stloc(local) .ldloc(local) .ldstr(property.Name) .call(propertyType.GetProperty(nameof(GeneralProperty.Name)).GetSetMethod()) .nop .ldloc(local) .ldtoken(property.Type) .call(MethodCache.TypeGetTypeFromHandle) .call(propertyType.GetProperty(nameof(GeneralProperty.Type)).GetSetMethod()) .nop .ldloc(local) .newobj(typeof(PropertyMapInfo)) .dup .ldstr(property.Info.FieldName) .call(mapType.GetProperty(nameof(PropertyMapInfo.FieldName)).GetSetMethod()) .nop; if (property.Info.IsPrimaryKey) { emiter = emiter.dup.ldc_i4_1.call(mapType.GetProperty(nameof(PropertyMapInfo.IsPrimaryKey)).GetSetMethod()).nop; } if (property.Info.GenerateType != IdentityGenerateType.None) { emiter = emiter.dup.ldc_i4_((int)property.Info.GenerateType).call(mapType.GetProperty(nameof(PropertyMapInfo.GenerateType)).GetSetMethod()).nop; } if (property.Info.DataType != null) { emiter = emiter.dup.ldc_i4_((int)property.Info.DataType).newobj(typeof(DbType?), typeof(DbType)).call(mapType.GetProperty(nameof(PropertyMapInfo.DataType)).GetSetMethod()).nop; } if (!string.IsNullOrEmpty(property.Info.Description)) { emiter = emiter.dup.ldstr(property.Info.Description).call(mapType.GetProperty(nameof(PropertyMapInfo.Description)).GetSetMethod()).nop; } if (property.Info.IsDeletedKey) { emiter = emiter.dup.ldc_i4_1.call(mapType.GetProperty(nameof(PropertyMapInfo.IsDeletedKey)).GetSetMethod()).nop; } if (property.Info.IsNullable) { emiter = emiter.dup.ldc_i4_1.call(mapType.GetProperty(nameof(PropertyMapInfo.IsNullable)).GetSetMethod()).nop; } if (property.Info.Precision != null) { emiter = emiter.dup.ldc_i4_((int)property.Info.Precision).newobj(typeof(int?), typeof(int)).call(mapType.GetProperty(nameof(PropertyMapInfo.Precision)).GetSetMethod()).nop; } if (property.Info.Scale != null) { emiter = emiter.dup.ldc_i4_((int)property.Info.Scale).newobj(typeof(int?), typeof(int)).call(mapType.GetProperty(nameof(PropertyMapInfo.Scale)).GetSetMethod()).nop; } if (property.Info.Length != null) { emiter = emiter.dup.ldc_i4_((int)property.Info.Length).newobj(typeof(int?), typeof(int)).call(mapType.GetProperty(nameof(PropertyMapInfo.Length)).GetSetMethod()).nop; } if (!PropertyValue.IsEmpty(property.Info.DefaultValue)) { //emiter = emiter.dup.ldc_i4_((int)property.Info.Length).newobj(typeof(int?), typeof(int)).call(mapType.GetProperty(nameof(PropertyMapInfo.Length)).GetSetMethod()).nop; } return(emiter.call(propertyType.GetProperty(nameof(GeneralProperty.Info)).GetSetMethod()) .ldloc(local) .call(MethodCache.RegisterProperty)); }
private void EmitSyncCall(List <ParameterInfo> parameters, EmitHelper emit) { Context.MethodBuilder.MethodBuilder.SetCustomAttribute(_soapDocumentAttributeBuilder); bool withOutParameters = EmitParameters(emit, parameters); bool callGeneric = !withOutParameters && Context.CurrentMethod.ReturnType != typeof(void); // Use Invoke<T>() for methods with return value but // Invoke() for methods with no return value or with out/ref parameters. // MethodInfo invoke = TypeHelper.GetMethod( typeof(WebClientBase), callGeneric, "Invoke", BindingFlags.Public | BindingFlags.Instance); if (callGeneric) { emit .call(invoke.MakeGenericMethod(Context.CurrentMethod.ReturnType)) .stloc(Context.ReturnValue) ; } else { if (withOutParameters) { LocalBuilder ret = emit.DeclareLocal(typeof(object[])); Label exit = emit.DefineLabel(); emit .call(invoke) .dup .stloc(ret) .brfalse_s(exit) ; int idx = 0; if (Context.CurrentMethod.ReturnType != typeof(void)) { emit .ldloc(ret) .ldc_i4_0 .ldelem_ref .CastFromObject(Context.CurrentMethod.ReturnType) .stloc(Context.ReturnValue) ; ++idx; } for (int i = 0; i < parameters.Count; ++i) { ParameterInfo pi = parameters[i]; Type type = pi.ParameterType; if (!type.IsByRef) { continue; } // Get ride of ref // type = type.GetElementType(); emit .ldarg(pi) .ldloc(ret) .ldc_i4_(idx) .ldelem_ref .CastFromObject(type) .stind(type) ; ++idx; } emit.MarkLabel(exit); } else { emit .call(invoke) .pop .end() ; } } }
private void GenerateCreateMethodCallIL(MethodBase method, ILGenerator generator, int argsIndex) { ParameterInfo[] args = method.GetParameters(); Label argsOk = generator.DefineLabel(); // throw an error if the number of argument values doesn't match method parameters generator.Emit(OpCodes.Ldarg, argsIndex); generator.Emit(OpCodes.Ldlen); generator.Emit(OpCodes.Ldc_I4, args.Length); generator.Emit(OpCodes.Beq, argsOk); generator.Emit(OpCodes.Newobj, typeof(TargetParameterCountException).GetConstructor(ReflectionUtils.EmptyTypes)); generator.Emit(OpCodes.Throw); generator.MarkLabel(argsOk); if (!method.IsConstructor && !method.IsStatic) { generator.PushInstance(method.DeclaringType); } int localVariableCount = 0; for (int i = 0; i < args.Length; i++) { ParameterInfo parameter = args[i]; Type parameterType = parameter.ParameterType; if (parameterType.IsByRef) { parameterType = parameterType.GetElementType(); LocalBuilder localVariable = generator.DeclareLocal(parameterType); // don't need to set variable for 'out' parameter if (!parameter.IsOut) { generator.PushArrayInstance(argsIndex, i); if (parameterType.IsValueType()) { Label skipSettingDefault = generator.DefineLabel(); Label finishedProcessingParameter = generator.DefineLabel(); // check if parameter is not null generator.Emit(OpCodes.Brtrue_S, skipSettingDefault); // parameter has no value, initialize to default generator.Emit(OpCodes.Ldloca_S, localVariable); generator.Emit(OpCodes.Initobj, parameterType); generator.Emit(OpCodes.Br_S, finishedProcessingParameter); // parameter has value, get value from array again and unbox and set to variable generator.MarkLabel(skipSettingDefault); generator.PushArrayInstance(argsIndex, i); generator.UnboxIfNeeded(parameterType); generator.Emit(OpCodes.Stloc, localVariableCount); // parameter finished, we out! generator.MarkLabel(finishedProcessingParameter); } else { generator.UnboxIfNeeded(parameterType); generator.Emit(OpCodes.Stloc, localVariableCount); } } generator.Emit(OpCodes.Ldloca_S, localVariable); localVariableCount++; } else if (parameterType.IsValueType()) { generator.PushArrayInstance(argsIndex, i); // have to check that value type parameters aren't null // otherwise they will error when unboxed Label skipSettingDefault = generator.DefineLabel(); Label finishedProcessingParameter = generator.DefineLabel(); // check if parameter is not null generator.Emit(OpCodes.Brtrue_S, skipSettingDefault); // parameter has no value, initialize to default LocalBuilder localVariable = generator.DeclareLocal(parameterType); generator.Emit(OpCodes.Ldloca_S, localVariable); generator.Emit(OpCodes.Initobj, parameterType); generator.Emit(OpCodes.Ldloc, localVariableCount); generator.Emit(OpCodes.Br_S, finishedProcessingParameter); // parameter has value, get value from array again and unbox generator.MarkLabel(skipSettingDefault); generator.PushArrayInstance(argsIndex, i); generator.UnboxIfNeeded(parameterType); // parameter finished, we out! generator.MarkLabel(finishedProcessingParameter); localVariableCount++; } else { generator.PushArrayInstance(argsIndex, i); generator.UnboxIfNeeded(parameterType); } } if (method.IsConstructor) { generator.Emit(OpCodes.Newobj, (ConstructorInfo)method); } else { generator.CallMethod((MethodInfo)method); } Type returnType = method.IsConstructor ? method.DeclaringType : ((MethodInfo)method).ReturnType; if (returnType != typeof(void)) { generator.BoxIfNeeded(returnType); } else { generator.Emit(OpCodes.Ldnull); } generator.Return(); }
private static DynamicMethod CreateIl2CppShim(DynamicMethod patch, MethodBase original) { var patchName = patch.Name + "_il2cpp"; var parameters = patch.GetParameters(); var result = parameters.Types().ToList(); var origParamTypes = result.ToArray(); var paramTypes = new Type[origParamTypes.Length]; for (int i = 0; i < paramTypes.Length; ++i) { paramTypes[i] = Il2CppTypeForPatchType(origParamTypes[i]); } var origReturnType = AccessTools.GetReturnedType(patch); var returnType = Il2CppTypeForPatchType(origReturnType); DynamicMethod method = new DynamicMethod( patchName, MethodAttributes.Public | MethodAttributes.Static, CallingConventions.Standard, returnType, paramTypes, original.DeclaringType, true ); for (var i = 0; i < parameters.Length; i++) { method.DefineParameter(i + 1, parameters[i].Attributes, parameters[i].Name); } var il = method.GetILGenerator(); LocalBuilder[] byRefValues = new LocalBuilder[parameters.Length]; LocalBuilder returnLocal = null; if (origReturnType != typeof(void)) { returnLocal = il.DeclareLocal(origReturnType); Emitter.LogLocalVariable(il, returnLocal); } LocalBuilder exceptionLocal = il.DeclareLocal(typeof(Exception)); Emitter.LogLocalVariable(il, exceptionLocal); // Start a try-block for the call to the original patch Emitter.MarkBlockBefore(il, new ExceptionBlock(ExceptionBlockType.BeginExceptionBlock, null), out _); // Load arguments, invoking the IntPrt -> Il2CppObject constructor for IL2CPP types for (int i = 0; i < origParamTypes.Length; ++i) { Emitter.Emit(il, OpCodes.Ldarg, i); ConvertArgument(il, origParamTypes[i], ref byRefValues[i]); if (byRefValues[i] != null) { Emitter.LogLocalVariable(il, byRefValues[i]); } } // Call the original patch with the now-correct types Emitter.Emit(il, OpCodes.Call, patch); // Store the result, if any if (returnLocal != null) { Emitter.Emit(il, OpCodes.Stloc, returnLocal); } // Catch any exceptions that may have been thrown Emitter.MarkBlockBefore(il, new ExceptionBlock(ExceptionBlockType.BeginCatchBlock, typeof(Exception)), out _); // CumLogger.LogError("Exception in ...\n" + exception.ToString()); Emitter.Emit(il, OpCodes.Stloc, exceptionLocal); Emitter.Emit(il, OpCodes.Ldstr, $"Exception in Harmony patch of method {original.FullDescription()}:\n"); Emitter.Emit(il, OpCodes.Ldloc, exceptionLocal); Emitter.Emit(il, OpCodes.Call, AccessTools.DeclaredMethod(typeof(Exception), "ToString", new Type[0])); Emitter.Emit(il, OpCodes.Call, AccessTools.DeclaredMethod(typeof(string), "Concat", new Type[] { typeof(string), typeof(string) })); Emitter.Emit(il, OpCodes.Call, AccessTools.DeclaredMethod(typeof(CumLogger), "LogError", new Type[] { typeof(string) })); // Close the exception block Emitter.MarkBlockAfter(il, new ExceptionBlock(ExceptionBlockType.EndExceptionBlock, null)); // Write back the pointers of ref arguments for (int i = 0; i < parameters.Length; ++i) { if (byRefValues[i] == null) { continue; } Emitter.Emit(il, OpCodes.Ldarg, i); // -> [intptr*] Emitter.Emit(il, OpCodes.Ldloc, byRefValues[i]); // -> [intptr*, obj] if (origParamTypes[i].GetElementType() == typeof(string)) { Emitter.Emit(il, OpCodes.Call, UnhollowerSupport.ManagedStringToIl2CppMethod); // -> [intptr*, intptr] } else { Emitter.Emit(il, OpCodes.Call, UnhollowerSupport.Il2CppObjectBaseToPtrMethod); // -> [intptr*, intptr] } Emitter.Emit(il, OpCodes.Stind_I); // -> [] } // Load the return value, if any, and unwrap it if required if (returnLocal != null) { Emitter.Emit(il, OpCodes.Ldloc, returnLocal); ConvertReturnValue(il, origReturnType); } Emitter.Emit(il, OpCodes.Ret); DynamicTools.PrepareDynamicMethod(method); return(method); }
public bool TryEmitDeserialiseCode(ILGenerator ilg, ThrowBlockGatherer throwBlocks, ICollection <string> errors, string name, Type targetType, LocalBuilder value, LocalBuilder unpacker, LocalBuilder contextLocal, DasherContext context, UnexpectedFieldBehaviour unexpectedFieldBehaviour) { ilg.Emit(OpCodes.Ldloc, unpacker); ilg.LoadType(targetType); ilg.Emit(OpCodes.Ldstr, name); ilg.Emit(OpCodes.Call, Methods.DecimalProvider_Parse); ilg.Emit(OpCodes.Stloc, value); return(true); }
private static void ConvertArgument(ILGenerator il, Type paramType, ref LocalBuilder byRefLocal) { if (paramType.IsValueType) { return; } if (paramType.IsByRef) { Type elementType = paramType.GetElementType(); if (paramType.GetElementType() == typeof(string)) { // byRefLocal = Il2CppStringToManaged(*ptr); // return ref byRefLocal; byRefLocal = il.DeclareLocal(elementType); Emitter.Emit(il, OpCodes.Ldind_I); Emitter.Emit(il, OpCodes.Call, UnhollowerSupport.Il2CppStringToManagedMethod); Emitter.Emit(il, OpCodes.Stloc, byRefLocal); Emitter.Emit(il, OpCodes.Ldloca, byRefLocal); } else if (UnhollowerSupport.IsGeneratedAssemblyType(elementType)) { // byRefLocal = *ptr == 0 ? null : new SomeType(*ptr); // return ref byRefLocal; Label ptrNonZero = il.DefineLabel(); Label done = il.DefineLabel(); byRefLocal = il.DeclareLocal(elementType); Emitter.Emit(il, OpCodes.Ldind_I); Emitter.Emit(il, OpCodes.Dup); Emitter.Emit(il, OpCodes.Brtrue_S, ptrNonZero); Emitter.Emit(il, OpCodes.Pop); Emitter.Emit(il, OpCodes.Br_S, done); Emitter.MarkLabel(il, ptrNonZero); Emitter.Emit(il, OpCodes.Newobj, Il2CppConstuctor(elementType)); Emitter.Emit(il, OpCodes.Stloc, byRefLocal); Emitter.MarkLabel(il, done); Emitter.Emit(il, OpCodes.Ldloca, byRefLocal); } } else if (paramType == typeof(string)) { // return Il2CppStringToManaged(ptr); Emitter.Emit(il, OpCodes.Call, UnhollowerSupport.Il2CppStringToManagedMethod); } else if (UnhollowerSupport.IsGeneratedAssemblyType(paramType)) { // return ptr == 0 ? null : new SomeType(ptr); Label ptrNonZero = il.DefineLabel(); Label done = il.DefineLabel(); Emitter.Emit(il, OpCodes.Dup); Emitter.Emit(il, OpCodes.Brtrue_S, ptrNonZero); Emitter.Emit(il, OpCodes.Pop); Emitter.Emit(il, OpCodes.Ldnull); Emitter.Emit(il, OpCodes.Br_S, done); Emitter.MarkLabel(il, ptrNonZero); Emitter.Emit(il, OpCodes.Newobj, Il2CppConstuctor(paramType)); Emitter.MarkLabel(il, done); } }
static Converter() { _type = typeof(T); TypeInfo typeInfo = _type.GetTypeInfo(); if (_type == typeof(string)) { _writeAction = (Converter.WriteAction <T>)(Delegate) new Converter.WriteAction <string>(StringConverter.Write); _readAction = (Converter.ReadAction <T>)(Delegate) new Converter.ReadAction <string>(StringConverter.Read); } else if (typeInfo.IsArray) { Type elementType = typeInfo.GetElementType(); _writeAction = (Converter.WriteAction <T>) typeof(Converter <>).MakeGenericType(elementType).GetTypeInfo().GetDeclaredMethod(nameof(WriteArray)).CreateDelegate(typeof(Converter.WriteAction <T>)); _readAction = (Converter.ReadAction <T>) typeof(Converter <>).MakeGenericType(elementType).GetTypeInfo().GetDeclaredMethod(nameof(ReadArray)).CreateDelegate(typeof(Converter.ReadAction <T>)); } else { try { if (typeInfo.IsUnmanaged()) { TypeInfo unmanagedType = typeof(UnmanagedConverter <>).MakeGenericType(_type).GetTypeInfo(); _writeAction = (Converter.WriteAction <T>)unmanagedType.GetDeclaredMethod(nameof(UnmanagedConverter <bool> .Write)).CreateDelegate(typeof(Converter.WriteAction <T>)); _readAction = (Converter.ReadAction <T>)unmanagedType.GetDeclaredMethod(nameof(UnmanagedConverter <bool> .Read)).CreateDelegate(typeof(Converter.ReadAction <T>)); } else { DynamicMethod writeMethod = new DynamicMethod($"Write_{nameof(T)}", typeof(void), new[] { _type.MakeByRefType(), typeof(Stream), typeof(byte[]), typeof(byte *) }, typeof(Converter <T>), true); ILGenerator writeGenerator = writeMethod.GetILGenerator(); DynamicMethod readMethod = new DynamicMethod($"Read_{nameof(T)}", _type, new[] { typeof(Stream), typeof(byte[]), typeof(byte *) }, typeof(Converter <T>), true); ILGenerator readGenerator = readMethod.GetILGenerator(); LocalBuilder readValue = readGenerator.DeclareLocal(_type); if (typeInfo.IsClass) { readGenerator.Emit(OpCodes.Ldsfld, typeof(Converter <T>).GetTypeInfo().GetDeclaredField(nameof(_type))); readGenerator.Emit(OpCodes.Call, typeof(ObjectInitializer).GetTypeInfo().GetDeclaredMethod(nameof(ObjectInitializer.Create))); readGenerator.Emit(OpCodes.Stloc, readValue); } else { readGenerator.Emit(OpCodes.Ldloca_S, readValue); readGenerator.Emit(OpCodes.Initobj, _type); } while (typeInfo != null) { foreach (FieldInfo fieldInfo in typeInfo.DeclaredFields.Where(f => !f.IsStatic)) { writeGenerator.Emit(OpCodes.Ldarg_0); if (typeInfo.IsClass) { writeGenerator.Emit(OpCodes.Ldind_Ref); } writeGenerator.Emit(OpCodes.Ldflda, fieldInfo); writeGenerator.Emit(OpCodes.Ldarg_1); writeGenerator.Emit(OpCodes.Ldarg_2); writeGenerator.Emit(OpCodes.Ldarg_3); writeGenerator.Emit(OpCodes.Call, typeof(Converter <>).MakeGenericType(fieldInfo.FieldType).GetTypeInfo().GetDeclaredMethod(nameof(Converter <T> .Write))); readGenerator.Emit(typeInfo.IsClass ? OpCodes.Ldloc : OpCodes.Ldloca_S, readValue); readGenerator.Emit(OpCodes.Ldarg_0); readGenerator.Emit(OpCodes.Ldarg_1); readGenerator.Emit(OpCodes.Ldarg_2); readGenerator.Emit(OpCodes.Call, typeof(Converter <>).MakeGenericType(fieldInfo.FieldType).GetTypeInfo().GetDeclaredMethod(nameof(Converter <T> .Read))); readGenerator.Emit(OpCodes.Stfld, fieldInfo); } typeInfo = typeInfo.BaseType?.GetTypeInfo(); } writeGenerator.Emit(OpCodes.Ret); _writeAction = (Converter.WriteAction <T>)writeMethod.CreateDelegate(typeof(Converter.WriteAction <T>)); readGenerator.Emit(OpCodes.Ldloc, readValue); readGenerator.Emit(OpCodes.Ret); _readAction = (Converter.ReadAction <T>)readMethod.CreateDelegate(typeof(Converter.ReadAction <T>)); } } catch { _writeAction = (in T _, Stream __, byte[] ___, byte *____) => throw new InvalidOperationException($"Unable to handle type {_type.FullName}"); _readAction = (_, __, ___) => throw new InvalidOperationException($"Unable to handle type {_type.FullName}"); } } }
/// <summary> /// 直接转换整个DataTable /// </summary> /// <typeparam name="T">model</typeparam> /// <param name="map">列名称映射:Key列名称,Value属性名称</param> /// <param name="mapType">列类型映射:key列类型,value属性类型</param> /// <returns></returns> public static DynamicMethod EntityToDataTableEmit <T>(Dictionary <string, string> map = null, Dictionary <string, Type> mapType = null) { DynamicMethod method = new DynamicMethod(typeof(T).Name + "ToDataTable", MethodAttributes.Public | MethodAttributes.Static, CallingConventions.Standard, null, new Type[] { typeof(DataTable), typeof(T) }, typeof(EntityContext).Module, true); ILGenerator generator = method.GetILGenerator(); //创建行 实现DataRow row=dt.NewRow(); LocalBuilder reslut = generator.DeclareLocal(typeof(DataRow)); generator.Emit(OpCodes.Ldarg_0); generator.Emit(OpCodes.Call, typeof(DataTable).GetMethod("NewRow")); generator.Emit(OpCodes.Stloc, reslut);//结果存储 var properties = typeof(T).GetProperties(); // Dictionary <string, Type> dic = new Dictionary <string, Type>(); Dictionary <string, LocalBuilder> dicLocalBuilder = new Dictionary <string, LocalBuilder>(); List <PropertyInfo> lstNull = new List <PropertyInfo>(); //获取空类型属性 foreach (var item in properties) { if (Nullable.GetUnderlyingType(item.PropertyType) != null) { lstNull.Add(item); } } int cout = lstNull.Count; List <LocalBuilder> lstLocal = new List <LocalBuilder>(lstNull.Count); foreach (var item in lstNull) { //获取所有空类型属性的类型 dic[item.Name] = item.PropertyType; } for (int i = 0; i < cout; i++) { //定义足够的bool lstLocal.Add(generator.DeclareLocal(typeof(bool))); } foreach (var kv in dic) { //定义包含的空类型 if (!dicLocalBuilder.ContainsKey(kv.Value.FullName)) { dicLocalBuilder[kv.Value.FullName] = generator.DeclareLocal(kv.Value); } } //没有列名称映射 int index = -1;//必须-1合适 if (map == null) { //遍历属性 foreach (var p in properties) { if (dic.ContainsKey(p.Name)) { var endIfLabel = generator.DefineLabel(); //判断 // generator.Emit(OpCodes.Ldarg_1); generator.Emit(OpCodes.Call, p.GetGetMethod());// generator.Emit(OpCodes.Stloc_S, dicLocalBuilder[p.PropertyType.FullName]); generator.Emit(OpCodes.Ldloca_S, dicLocalBuilder[p.PropertyType.FullName]); generator.Emit(OpCodes.Call, dic[p.Name].GetMethod("get_HasValue")); generator.Emit(OpCodes.Stloc, lstLocal[++index]); generator.Emit(OpCodes.Ldloc, lstLocal[index]); generator.Emit(OpCodes.Brfalse_S, endIfLabel); //赋值 generator.Emit(OpCodes.Ldloc, reslut); //取出变量 generator.Emit(OpCodes.Ldstr, p.Name); //row["Name"] generator.Emit(OpCodes.Ldarg_1); generator.Emit(OpCodes.Call, p.GetGetMethod()); // // generator.Emit(OpCodes.Stloc_S, dicLocalBuilder[p.PropertyType.FullName]); generator.Emit(OpCodes.Ldloca_S, dicLocalBuilder[p.PropertyType.FullName]); generator.Emit(OpCodes.Call, dic[p.Name].GetMethod("get_Value")); // generator.Emit(OpCodes.Box, Nullable.GetUnderlyingType(p.PropertyType)); //一直在折腾这个地方,哎 // generator.Emit(OpCodes.Call, typeof(DataRow).GetMethod("set_Item", new Type[] { typeof(string), typeof(object) })); generator.MarkLabel(endIfLabel); } else { generator.Emit(OpCodes.Ldloc, reslut); generator.Emit(OpCodes.Ldstr, p.Name); generator.Emit(OpCodes.Ldarg_1); generator.Emit(OpCodes.Call, p.GetGetMethod());//获取属性 if (mapType == null || !mapType.ContainsKey(p.Name)) { if (p.PropertyType.IsValueType) { generator.Emit(OpCodes.Box, p.PropertyType);//一直在折腾这个地方,哎 } else { generator.Emit(OpCodes.Castclass, p.PropertyType); } } else { generator.Emit(OpCodes.Ldtoken, mapType[p.Name]); generator.Emit(OpCodes.Call, typeof(Type).GetMethod("GetTypeFromHandle")); generator.Emit(OpCodes.Call, typeof(Convert).GetMethod("ChangeType", new Type[] { typeof(object), typeof(Type) })); } generator.Emit(OpCodes.Call, typeof(DataRow).GetMethod("set_Item", new Type[] { typeof(string), typeof(object) })); } } generator.Emit(OpCodes.Ldarg_0); generator.Emit(OpCodes.Call, typeof(DataTable).GetMethod("get_Rows")); generator.Emit(OpCodes.Ldloc, reslut); generator.Emit(OpCodes.Call, typeof(DataRowCollection).GetMethod("Add", new Type[] { typeof(DataRow) })); generator.Emit(OpCodes.Ret); } else { List <PropertyInfo> lst = new List <PropertyInfo>(properties); foreach (var kv in map) { var p = lst.Find(x => x.Name == kv.Value);//找到属性 if (dic.ContainsKey(p.Name)) { var endIfLabel = generator.DefineLabel(); //判断 // generator.Emit(OpCodes.Ldarg_1); generator.Emit(OpCodes.Call, p.GetGetMethod());// generator.Emit(OpCodes.Stloc_S, dicLocalBuilder[p.PropertyType.FullName]); generator.Emit(OpCodes.Ldloca_S, dicLocalBuilder[p.PropertyType.FullName]); generator.Emit(OpCodes.Call, dic[p.Name].GetMethod("get_HasValue")); generator.Emit(OpCodes.Stloc, lstLocal[++index]); generator.Emit(OpCodes.Ldloc, lstLocal[index]); generator.Emit(OpCodes.Brfalse_S, endIfLabel); //赋值 generator.Emit(OpCodes.Ldloc, reslut); generator.Emit(OpCodes.Ldstr, kv.Value); //属性名称 generator.Emit(OpCodes.Ldarg_1); generator.Emit(OpCodes.Call, p.GetGetMethod()); // // generator.Emit(OpCodes.Stloc_S, dicLocalBuilder[p.PropertyType.FullName]); generator.Emit(OpCodes.Ldloca_S, dicLocalBuilder[p.PropertyType.FullName]); generator.Emit(OpCodes.Call, dic[p.Name].GetMethod("get_Value")); // generator.Emit(OpCodes.Box, Nullable.GetUnderlyingType(p.PropertyType)); //一直在折腾这个地方,哎 // generator.Emit(OpCodes.Call, typeof(DataRow).GetMethod("set_Item", new Type[] { typeof(string), typeof(object) })); generator.MarkLabel(endIfLabel); } else { generator.Emit(OpCodes.Ldloc, reslut); generator.Emit(OpCodes.Ldstr, kv.Value); //属性名称 generator.Emit(OpCodes.Ldarg_1); generator.Emit(OpCodes.Call, p.GetGetMethod()); //获取属性值 if (mapType == null || !mapType.ContainsKey(kv.Key)) { if (p.PropertyType.IsValueType) { generator.Emit(OpCodes.Box, p.PropertyType);//一直在折腾这个地方,哎 } else { generator.Emit(OpCodes.Castclass, p.PropertyType); } } else { generator.Emit(OpCodes.Ldtoken, mapType[kv.Key]); generator.Emit(OpCodes.Call, typeof(Type).GetMethod("GetTypeFromHandle")); generator.Emit(OpCodes.Call, typeof(Convert).GetMethod("ChangeType", new Type[] { typeof(object), typeof(Type) })); } generator.Emit(OpCodes.Call, typeof(DataRow).GetMethod("set_Item", new Type[] { typeof(string), typeof(object) })); } } generator.Emit(OpCodes.Ldarg_0); generator.Emit(OpCodes.Call, typeof(DataTable).GetMethod("get_Rows")); generator.Emit(OpCodes.Ldloc, reslut); generator.Emit(OpCodes.Call, typeof(DataRowCollection).GetMethod("Add", new Type[] { typeof(DataRow) })); generator.Emit(OpCodes.Ret); } return(method); }
/// <summary> /// Creates a method for calling with the specified signature. The returned method has a signature /// of the form: /// /// (IntPtr funcAddress, arg0, arg1, ..., object[] constantPool) /// /// where IntPtr is the address of the function to be called. The arguments types are based upon /// the types that the ArgumentMarshaller requires. /// </summary> private static MethodInfo /*!*/ CreateInteropInvoker(CallingConvention convention, ArgumentMarshaller /*!*/[] /*!*/ sig, INativeType nativeRetType, bool retVoid, List <object> constantPool) { Type[] sigTypes = new Type[sig.Length + 2]; sigTypes[0] = typeof(IntPtr); for (int i = 0; i < sig.Length; i++) { sigTypes[i + 1] = sig[i].ArgumentExpression.Type; } sigTypes[sigTypes.Length - 1] = typeof(object[]); Type retType = retVoid ? typeof(void) : nativeRetType != null?nativeRetType.GetPythonType() : typeof(int); Type calliRetType = retVoid ? typeof(void) : nativeRetType != null?nativeRetType.GetNativeType() : typeof(int); #if !CTYPES_USE_SNIPPETS DynamicMethod dm = new DynamicMethod("InteropInvoker", retType, sigTypes, DynamicModule); #else TypeGen tg = Snippets.Shared.DefineType("InteropInvoker", typeof(object), false, false); MethodBuilder dm = tg.TypeBuilder.DefineMethod("InteropInvoker", CompilerHelpers.PublicStatic, retType, sigTypes); #endif ILGenerator method = dm.GetILGenerator(); LocalBuilder calliRetTmp = null, finalRetValue = null; if (dm.ReturnType != typeof(void)) { calliRetTmp = method.DeclareLocal(calliRetType); finalRetValue = method.DeclareLocal(dm.ReturnType); } // try { // emit all of the arguments, save their cleanups method.BeginExceptionBlock(); List <MarshalCleanup> cleanups = null; for (int i = 0; i < sig.Length; i++) { #if DEBUG method.Emit(OpCodes.Ldstr, String.Format("Argument #{0}, Marshaller: {1}, Native Type: {2}", i, sig[i], sig[i].NativeType)); method.Emit(OpCodes.Pop); #endif MarshalCleanup cleanup = sig[i].EmitCallStubArgument(method, i + 1, constantPool, sigTypes.Length - 1); if (cleanup != null) { if (cleanups == null) { cleanups = new List <MarshalCleanup>(); } cleanups.Add(cleanup); } } // emit the target function pointer and the calli #if DEBUG method.Emit(OpCodes.Ldstr, "!!! CALLI !!!"); method.Emit(OpCodes.Pop); #endif method.Emit(OpCodes.Ldarg_0); method.Emit(OpCodes.Calli, GetCalliSignature(convention, sig, calliRetType)); // if we have a return value we need to store it and marshal to Python // before we run any cleanup code. if (retType != typeof(void)) { #if DEBUG method.Emit(OpCodes.Ldstr, "!!! Return !!!"); method.Emit(OpCodes.Pop); #endif if (nativeRetType != null) { method.Emit(OpCodes.Stloc, calliRetTmp); nativeRetType.EmitReverseMarshalling(method, new Local(calliRetTmp), constantPool, sig.Length + 1); method.Emit(OpCodes.Stloc, finalRetValue); } else { Debug.Assert(retType == typeof(int)); // no marshalling necessary method.Emit(OpCodes.Stloc, finalRetValue); } } // } finally { // emit the cleanup code method.BeginFinallyBlock(); if (cleanups != null) { foreach (MarshalCleanup mc in cleanups) { mc.Cleanup(method); } } method.EndExceptionBlock(); // } // load the temporary value and return it. if (retType != typeof(void)) { method.Emit(OpCodes.Ldloc, finalRetValue); } method.Emit(OpCodes.Ret); #if CTYPES_USE_SNIPPETS return(tg.TypeBuilder.CreateType().GetMethod("InteropInvoker")); #else return(dm); #endif }
private static void EmitReadMethodContents( ILGenerator gen, Type formattedType, FieldInfo dictField, Dictionary <Type, FieldBuilder> serializerFields, Dictionary <MemberInfo, List <string> > memberNames, Dictionary <Type, MethodInfo> serializerReadMethods) { MethodInfo skipMethod = typeof(IDataReader).GetMethod("SkipEntry", Flags.InstancePublic); MethodInfo tryGetValueMethod = typeof(Dictionary <string, int>).GetMethod("TryGetValue", Flags.InstancePublic); //methodBuilder.DefineParameter(5, ParameterAttributes.None, "switchLookup"); LocalBuilder lookupResult = gen.DeclareLocal(typeof(int)); Label defaultLabel = gen.DefineLabel(); Label switchLabel = gen.DefineLabel(); Label endLabel = gen.DefineLabel(); Label[] switchLabels = memberNames.Select(n => gen.DefineLabel()).ToArray(); gen.Emit(OpCodes.Ldarg_1); // Load entryName string gen.Emit(OpCodes.Ldnull); // Load null gen.Emit(OpCodes.Ceq); // Equality check gen.Emit(OpCodes.Brtrue, defaultLabel); // If entryName is null, go to default case //gen.Emit(OpCodes.Ldarg, (short)4); // Load lookup dictionary argument (OLD CODE) gen.Emit(OpCodes.Ldsfld, dictField); // Load lookup dictionary from static field on helper type gen.Emit(OpCodes.Ldarg_1); // Load entryName string gen.Emit(OpCodes.Ldloca, (short)lookupResult.LocalIndex); // Load address of lookupResult gen.Emit(OpCodes.Callvirt, tryGetValueMethod); // Call TryGetValue on the dictionary gen.Emit(OpCodes.Brtrue, switchLabel); // If TryGetValue returned true, go to the switch case gen.Emit(OpCodes.Br, defaultLabel); // Else, go to the default case gen.MarkLabel(switchLabel); // Switch starts here gen.Emit(OpCodes.Ldloc, lookupResult); // Load lookupResult gen.Emit(OpCodes.Switch, switchLabels); // Perform switch on switchLabels int count = 0; foreach (var member in memberNames.Keys) { var memberType = FormatterUtilities.GetContainedType(member); var propInfo = member as PropertyInfo; var fieldInfo = member as FieldInfo; gen.MarkLabel(switchLabels[count]); // Switch case for [count] starts here // Now we load the instance that we have to set the value on gen.Emit(OpCodes.Ldarg_0); // Load value reference if (formattedType.IsValueType == false) { gen.Emit(OpCodes.Ldind_Ref); // Indirectly load value of reference } // Now we deserialize the value itself gen.Emit(OpCodes.Ldsfld, serializerFields[memberType]); // Load serializer from serializer container type gen.Emit(OpCodes.Ldarg, (short)3); // Load reader argument gen.Emit(OpCodes.Callvirt, serializerReadMethods[memberType]); // Call Serializer.ReadValue(IDataReader reader) // The stack now contains the formatted instance and the deserialized value to set the member to // Now we set the value if (fieldInfo != null) { gen.Emit(OpCodes.Stfld, fieldInfo.DeAliasField()); // Set field } else if (propInfo != null) { gen.Emit(OpCodes.Callvirt, propInfo.DeAliasProperty().GetSetMethod(true)); // Call property setter } else { throw new NotImplementedException(); } gen.Emit(OpCodes.Br, endLabel); // Jump to end of method count++; } gen.MarkLabel(defaultLabel); // Default case starts here gen.Emit(OpCodes.Ldarg, (short)3); // Load reader argument gen.Emit(OpCodes.Callvirt, skipMethod); // Call IDataReader.SkipEntry gen.MarkLabel(endLabel); // Method end starts here gen.Emit(OpCodes.Ret); // Return method }
internal override void GenStatementCode(CompileContext compileContext, bool bGenDebug) { LocalBuilder thrownException = compileContext.gen.DeclareLocal(typeof(JSRuntimeException)); Label exTryCatchFinally = compileContext.gen.BeginExceptionBlock(); this.FinallyFwdDest = compileContext.gen.DeclareLocal(typeof(int)); compileContext.gen.Emit(OpCodes.Ldc_I4_M1); compileContext.gen.Emit(OpCodes.Stloc, this.FinallyFwdDest); this.FinEnd = compileContext.gen.DefineLabel(); ((StatementNode) base.Children[0]).GenCode(compileContext); compileContext.gen.MarkLabel(this.FinEnd); if (this.CatchTree != null) { compileContext.gen.BeginCatchBlock(typeof(JSRuntimeException)); compileContext.gen.Emit(OpCodes.Stloc, thrownException); compileContext.gen.Emit(OpCodes.Ldarg_0); compileContext.gen.Emit(OpCodes.Ldloc, thrownException); compileContext.gen.Emit(OpCodes.Ldstr, this.CatchId); compileContext.gen.EmitCallV( CompileContext.mi_JSScope_CreateCatchScope); compileContext.gen.Emit(OpCodes.Starg, 0); Label InternalTry = compileContext.gen.BeginExceptionBlock(); this.FinEnd = compileContext.gen.DefineLabel(); this.CatchTree.GenCode(compileContext); compileContext.gen.MarkLabel(this.FinEnd); compileContext.gen.BeginFinallyBlock(); compileContext.gen.Emit(OpCodes.Ldarg_0); compileContext.gen.EmitCallV( CompileContext.mi_JSContext_Parent); compileContext.gen.Emit(OpCodes.Starg, 0); compileContext.gen.EndExceptionBlock(); } else if (this.FinallyTree != null) { compileContext.gen.BeginCatchBlock(typeof(JSRuntimeException)); compileContext.gen.Emit(OpCodes.Stloc, thrownException); } if (this.FinallyTree != null) { this.FinEnd = compileContext.gen.DefineLabel(); compileContext.gen.BeginFinallyBlock(); this.FinallyTree.GenCode(compileContext); compileContext.gen.MarkLabel(this.FinEnd); } compileContext.gen.EndExceptionBlock(); bool bProcessRedirects = this.PostFinallyLabels.Count > 0; if (bProcessRedirects) { compileContext.gen.Emit(OpCodes.Ldloc, this.FinallyFwdDest); compileContext.gen.Emit(OpCodes.Switch, this.PostFinallyLabels.Select<PostFinallyLabel, Label>(delegate (PostFinallyLabel x) { return x.switchlabel; }).ToArray<Label>()); } if ((this.CatchTree == null) && (this.FinallyTree != null)) { compileContext.gen.Emit(OpCodes.Ldloc, thrownException); compileContext.gen.Emit(OpCodes.Brfalse, base.breakdest); compileContext.gen.Emit(OpCodes.Ldloc, thrownException); compileContext.gen.Emit(OpCodes.Throw); } else { compileContext.gen.Emit(OpCodes.Br, base.breakdest); } if (bProcessRedirects) { foreach (PostFinallyLabel pfl in this.PostFinallyLabels) { compileContext.gen.MarkLabel(pfl.switchlabel); base.GenInterStatementBreak(compileContext, pfl.lbl, pfl.destNode); } } }
/// <summary> /// *********************************************************************** /// V1: Not nullable object. ex) Int32, DateTime, Point, DayOfWeek /// P1: Nullable object. ex) String, class, Nullable<T> /// ----------------------------------------------------------------------- /// src.V1 --> tgt.V1; /// var converted = converter.ToXXX(src.V1); /// if (converted == null) return; // DoNothing... /// tgt.V1 = converted.Value; /// /// ----------------------------------------------------------------------- /// src.V1 --> tgt.P1; /// var converted = converter.ToXXX(src.V1); /// if (converted == null) return; // DoNothing... /// tgt.P1 = converted; /// /// ----------------------------------------------------------------------- /// src.P1 --> tgt.V1; /// if (src.P1 == null) return; // DoNothing... /// var converted = converter.ToXXX(src.P1); /// if (converted.HasValue == false) return; // DoNothing... /// tgt.V1 = converted; /// /// ----------------------------------------------------------------------- /// src.P1 --> tgt.P1; /// if (src.P1 == null) tgt.P1 = null; /// var converted = converter.ToXXX(src.P1); /// if (converted.HasValue == false) return; // DoNothing... /// tgt.P1 = converted; /// /// *************************************************************************/ /// </summary> /// <typeparam name="TSource"></typeparam> /// <typeparam name="TTarget"></typeparam> /// <param name="propertyMapInfo"></param> /// <returns></returns> private Action <ObjectMapConfig, TSource, TTarget, MappingContext> CreateSetPropertyMethod <TSource, TTarget>(IEnumerable <PropertyMap> propertyMapInfo) { var sourceType = typeof(TSource); var targetType = typeof(TTarget); DynamicMethod dm = new DynamicMethod("SetProperty", null, new[] { typeof(ObjectMapConfig), sourceType, targetType, typeof(MappingContext) }); ILGenerator il = dm.GetILGenerator(); var mapConfigTypeConverterGetMethod = typeof(ObjectMapConfig).GetProperty("TypeConverter", BindingFlags.Instance | BindingFlags.Public).GetGetMethod(); il.DeclareLocal(typeof(TypeConverter)); il.Emit(OpCodes.Nop); il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Callvirt, mapConfigTypeConverterGetMethod); il.Emit(OpCodes.Stloc_0);//ObjectMapConfig.TypeConverter foreach (var item in propertyMapInfo) { var getMethod = item.Source.PropertyInfo.GetGetMethod(); var setMethod = item.Target.PropertyInfo.GetSetMethod(); //Target property is readonly if (setMethod == null) { continue; } #region DefineLabel Label customConvertStartLabel = il.DefineLabel(); Label setValueStartLabel = il.DefineLabel(); Label endOfCode = il.DefineLabel(); Label setNullToTargetLabel = il.DefineLabel(); Label sourceHasValueLabel = il.DefineLabel(); #endregion var sourceVal = il.DeclareLocal(item.Source.ActualType); var targetVal = il.DeclareLocal(item.Target.ActualType); #region GetValue from SourceObject if (item.Source.IsIndexedProperty == true) { #region Dictionary<String, String> or Dictionary<String, Object> //Call TryGetValue method to avoid KeyNotFoundException if (sourceType.IsInheritanceFrom(typeof(Dictionary <String, String>)) == true || sourceType.IsInheritanceFrom(typeof(Dictionary <String, Object>)) == true) { MethodInfo tryGetValue = null; LocalBuilder outValue = null; //Call TryGetValue method tryGetValue = sourceType.GetMethod("TryGetValue"); outValue = il.DeclareLocal(item.Source.PropertyType); il.Emit(OpCodes.Ldarg_1); il.Emit(OpCodes.Ldstr, item.Source.IndexedPropertyKey); il.LoadLocala(outValue); //TryGetValue(item.Source.IndexedPropertyKey, sourceVal) --> Boolean il.Emit(OpCodes.Callvirt, tryGetValue); il.Emit(OpCodes.Pop); il.LoadLocal(outValue); } else { //source[string key] il.Emit(OpCodes.Ldarg_1); il.Emit(OpCodes.Ldstr, item.Source.IndexedPropertyKey); il.Emit(OpCodes.Callvirt, getMethod); } #endregion } else { il.Emit(OpCodes.Ldarg_1); il.Emit(OpCodes.Callvirt, getMethod); } //Check source.P1 is null if (item.Source.CanBeNull == true) { if (item.Source.IsNullableT == true) { #region if (source.P1.HasValue == false) var sourceValN = il.DeclareLocal(item.Source.PropertyType); il.SetLocal(sourceValN); //if (sourceValue.HasValue == true) il.LoadLocala(sourceValN); il.Emit(OpCodes.Call, item.Source.PropertyType.GetProperty("HasValue").GetGetMethod()); il.Emit(OpCodes.Brfalse, setNullToTargetLabel); //null --> set target null il.LoadLocala(sourceValN); //sourceVal.Value il.Emit(OpCodes.Call, item.Source.PropertyType.GetMethod("GetValueOrDefault", Type.EmptyTypes)); #endregion } else if (item.Source.CanBeNull == true) { #region if (source.P1 == null) Type sourceTypeN = item.Source.ActualType; var sourceValN = il.DeclareLocal(sourceTypeN); il.SetLocal(sourceValN); //if (sourceValue == null) il.LoadLocal(sourceValN); il.Emit(OpCodes.Ldnull); il.Emit(OpCodes.Ceq); il.Emit(OpCodes.Brtrue, setNullToTargetLabel); //null --> set target null il.LoadLocal(sourceValN); #endregion } } il.Emit(OpCodes.Br, sourceHasValueLabel); il.MarkLabel(sourceHasValueLabel); //store sourceVal (never be null) il.SetLocal(sourceVal); #endregion #region Convert value to target type. LocalBuilder convertedVal = null; var methodName = GetMethodName(item.Target.ActualType); if (item.Target.ActualType.IsEnum == false && methodName == null) { if (item.Target.PropertyType.IsValueType == true && item.Source.ActualType == item.Target.ActualType) { #region target.Struct = source.Struct; il.LoadLocal(sourceVal); il.LoadLocal(targetVal); #endregion } else { convertedVal = il.DeclareLocal(item.Target.ActualType); il.Emit(OpCodes.Br_S, customConvertStartLabel); } } else { #region var convertedValue = TypeConverter.ToXXX(sourceVal); //Call TypeConverter.ToXXX(sourceVal); il.Emit(OpCodes.Ldloc_0);//MapConfig.Current.TypeConverter il.LoadLocal(sourceVal); if (item.Source.ActualType.IsValueType == true) { il.Emit(OpCodes.Box, item.Source.ActualType); } if (item.Target.ActualType.IsEnum == true) { il.Emit(OpCodes.Callvirt, typeof(TypeConverter).GetMethod("ToEnum", new Type[] { typeof(Object) }).MakeGenericMethod(item.Target.ActualType)); } else { il.Emit(OpCodes.Callvirt, typeof(TypeConverter).GetMethod(methodName, new Type[] { typeof(Object) })); } Label ifConvertedValueNotNullBlock = il.DefineLabel(); if (item.Target.ActualType == typeof(String)) { convertedVal = il.DeclareLocal(item.Target.ActualType); il.SetLocal(targetVal); il.LoadLocal(targetVal); il.Emit(OpCodes.Ldnull); il.Emit(OpCodes.Ceq); il.Emit(OpCodes.Brfalse_S, ifConvertedValueNotNullBlock); { //DoNothing when convert failed il.Emit(OpCodes.Br_S, customConvertStartLabel); } il.MarkLabel(ifConvertedValueNotNullBlock); } else { Type targetTypeN = typeof(Nullable <>).MakeGenericType(item.Target.ActualType); convertedVal = il.DeclareLocal(targetTypeN); //SetValue to TargetObject il.SetLocal(convertedVal); il.LoadLocala(convertedVal); il.Emit(OpCodes.Call, targetTypeN.GetProperty("HasValue").GetGetMethod()); il.Emit(OpCodes.Brtrue_S, ifConvertedValueNotNullBlock); { //Try custom convert when convert failed il.Emit(OpCodes.Br_S, customConvertStartLabel); } il.MarkLabel(ifConvertedValueNotNullBlock); //GetValue il.LoadLocala(convertedVal); il.Emit(OpCodes.Call, targetTypeN.GetMethod("GetValueOrDefault", Type.EmptyTypes)); il.SetLocal(targetVal); } #endregion } il.Emit(OpCodes.Br_S, setValueStartLabel); #endregion #region Call custom convert method or Map method when convert failed. //ObjectMapConfig.Current.Convert<T>(...) il.MarkLabel(customConvertStartLabel); convertedVal = il.DeclareLocal(item.Target.ActualType); //Set up parameter for ObjectMapConfig.Convert<>(sourceVal, convertedVal) il.Emit(OpCodes.Ldarg_0);//ObjectMapConfig instance il.LoadLocal(sourceVal); if (item.Source.ActualType.IsValueType == true) { //Boxing to Object il.Emit(OpCodes.Box, item.Source.ActualType); } il.LoadLocala(convertedVal); //public Boolean Convert<T>(Object value, out T convertedValue) il.Emit(OpCodes.Call, _ConvertMethod.MakeGenericMethod(item.Target.ActualType)); var convertResult = il.DeclareLocal(typeof(Boolean)); il.SetLocal(convertResult); il.LoadLocal(convertedVal); il.SetLocal(targetVal); il.LoadLocal(convertResult); il.Emit(OpCodes.Brtrue, setValueStartLabel); if (item.Target.IsIndexedProperty == false) { //Try Map method when convert failed #region source.P1.Map(target.P1); //Call Map method var targetObj = il.DeclareLocal(item.Target.PropertyType); il.Emit(OpCodes.Ldarg_2); il.Emit(OpCodes.Callvirt, item.Target.PropertyInfo.GetGetMethod()); il.SetLocal(targetObj); il.Emit(OpCodes.Ldarg_0);//ObjectMapConfig instance il.LoadLocal(sourceVal); il.LoadLocal(targetObj); il.Emit(OpCodes.Ldarg_3);//MappingContext il.Emit(OpCodes.Call, _MapMethod.MakeGenericMethod(item.Source.ActualType, item.Target.PropertyType)); il.Emit(OpCodes.Pop); il.Emit(OpCodes.Br, endOfCode); #endregion } #endregion #region Set Null to Target property //tgt.P1 = null il.MarkLabel(setNullToTargetLabel); { if (item.Target.CanBeNull == true) { il.Emit(OpCodes.Ldarg_2); if (item.Target.IsIndexedProperty == true) { //target["P1"] = source.P1; il.Emit(OpCodes.Ldstr, item.Target.IndexedPropertyKey); } if (item.Target.IsNullableT == true) { var targetValN = il.DeclareLocal(item.Target.PropertyType); il.LoadLocala(targetValN); il.Emit(OpCodes.Initobj, item.Target.PropertyType); il.LoadLocal(targetValN); } else { il.Emit(OpCodes.Ldnull); } il.Emit(OpCodes.Callvirt, setMethod); } il.Emit(OpCodes.Br_S, endOfCode); } #endregion #region Set value to TargetProperty il.MarkLabel(setValueStartLabel); il.Emit(OpCodes.Ldarg_2); if (item.Target.IsIndexedProperty == true) { //target["P1"] = source.P1; il.Emit(OpCodes.Ldstr, item.Target.IndexedPropertyKey); } il.LoadLocal(targetVal); if (item.Target.IsNullableT == true) { //new Nullable<T>(new T()); il.Emit(OpCodes.Newobj, item.Target.PropertyType.GetConstructor(new Type[] { item.Target.ActualType })); } il.Emit(OpCodes.Callvirt, setMethod); #endregion il.MarkLabel(endOfCode); il.Emit(OpCodes.Nop); } il.Emit(OpCodes.Ret); var f = typeof(Action <, , ,>); var gf = f.MakeGenericType(typeof(ObjectMapConfig), sourceType, targetType, typeof(MappingContext)); return((Action <ObjectMapConfig, TSource, TTarget, MappingContext>)dm.CreateDelegate(gf)); }
internal static Instruction Create(OpCode opcode, LocalBuilder lvar) { Instruction i = new Instruction(); i.opCode = opcode; i.type = InstructionType.OpCode; i.operand = lvar; i.operandType = typeof(LocalBuilder); return i; }
/// <summary> /// Creates the SpringServicedComponent base class to derive all <see cref="ServicedComponent"/>s from. /// </summary> /// <example> /// <code> /// internal class SpringServicedComponent: BaseType /// { /// protected delegate object GetObjectHandler(ServicedComponent servicedComponent, string targetName); /// /// protected static readonly GetObjectHandler getObjectRef; /// /// static SpringServicedComponent() /// { /// // first look for a local copy /// System.Reflection.Assembly servicesAssembly; /// string servicesAssemblyPath = Path.Combine( /// new FileInfo(System.Reflection.Assembly.GetExecutingAssembly().Location).DirectoryName /// , "Spring.Services.dll" ); /// servicesAssembly = System.Reflection.Assembly.LoadFrom(servicesAssemblyPath); /// if (servicesAssembly == null) /// { /// // then let the normal loader handle the typeload /// servicesAssembly = System.Reflection.Assembly.Load("Spring.Services, culture=neutral, version=x.x.x.x, publicKey=xxxxxxxx"); /// } /// /// Type componentHelperType = servicesAssembly.GetType("Spring.EnterpriseServices.ServicedComponentHelper"); /// getObjectRef = (GetObjectHandler) Delegate.CreateDelegate(typeof(GetObjectHandler) /// , componentHelperType.GetMethod("GetObject")); /// } /// } /// </code> /// </example> public static Type CreateSpringServicedComponentType(ModuleBuilder module, Type baseType) { if (!typeof(ServicedComponent).IsAssignableFrom(baseType)) { throw new ArgumentException(string.Format("baseType must derive from {0}, was {1}", typeof(ServicedComponent).FullName, baseType), "baseType"); } Type delegateType = DefineDelegate(module); TypeBuilder typeBuilder = module.DefineType("SpringServicedComponent", System.Reflection.TypeAttributes.Public, baseType); ILGenerator il = null; FieldBuilder getObjectRef = typeBuilder.DefineField("getObject", delegateType, FieldAttributes.Family | FieldAttributes.Static); ConstructorBuilder typeCtor = typeBuilder.DefineTypeInitializer(); il = typeCtor.GetILGenerator(); Label methodEnd = il.DefineLabel(); Label loadType = il.DefineLabel(); Label tryBegin = il.BeginExceptionBlock(); LocalBuilder fldAssembly = il.DeclareLocal(typeof(Assembly)); LocalBuilder fldType = il.DeclareLocal(typeof(Type)); LocalBuilder fldArgs = il.DeclareLocal(typeof(object[])); LocalBuilder fldMethod = il.DeclareLocal(typeof(MethodBase)); il.Emit(OpCodes.Call, typeof(Assembly).GetMethod("GetExecutingAssembly")); il.Emit(OpCodes.Callvirt, typeof(Assembly).GetProperty("Location").GetGetMethod()); il.Emit(OpCodes.Newobj, typeof(FileInfo).GetConstructor(new Type[] { typeof(string) })); il.Emit(OpCodes.Call, typeof(FileInfo).GetProperty("DirectoryName").GetGetMethod()); il.Emit(OpCodes.Ldstr, new FileInfo(typeof(ServicedComponentHelper).Assembly.Location).Name); il.Emit(OpCodes.Call, typeof(Path).GetMethod("Combine", new Type[] { typeof(string), typeof(string) })); il.Emit(OpCodes.Call, typeof(Assembly).GetMethod("LoadFrom", new Type[] { typeof(string) })); il.Emit(OpCodes.Stloc, fldAssembly); il.Emit(OpCodes.Ldloc, fldAssembly); il.Emit(OpCodes.Ldnull); il.Emit(OpCodes.Ceq); il.Emit(OpCodes.Ldc_I4_0); il.Emit(OpCodes.Ceq); il.Emit(OpCodes.Brtrue_S, loadType); il.Emit(OpCodes.Ldstr, typeof(ServicedComponentHelper).Assembly.FullName); il.Emit(OpCodes.Call, typeof(Assembly).GetMethod("Load", new Type[] { typeof(string) })); il.Emit(OpCodes.Stloc, fldAssembly); il.MarkLabel(loadType); il.Emit(OpCodes.Ldloc, fldAssembly); il.Emit(OpCodes.Ldstr, typeof(ServicedComponentHelper).FullName); il.Emit(OpCodes.Ldc_I4_1); il.Emit(OpCodes.Call, typeof(Assembly).GetMethod("GetType", new Type[] { typeof(string), typeof(bool) })); il.Emit(OpCodes.Stloc, fldType); il.Emit(OpCodes.Ldtoken, delegateType); il.Emit(OpCodes.Call, typeof(Type).GetMethod("GetTypeFromHandle")); il.Emit(OpCodes.Ldloc, fldType); il.Emit(OpCodes.Ldstr, "GetObject"); il.Emit(OpCodes.Callvirt, typeof(Type).GetMethod("GetMethod", new Type[] { typeof(string) })); il.Emit(OpCodes.Call, typeof(Delegate).GetMethod("CreateDelegate", new Type[] { typeof(Type), typeof(MethodInfo) })); il.Emit(OpCodes.Castclass, delegateType); il.Emit(OpCodes.Stsfld, getObjectRef); il.Emit(OpCodes.Ldc_I4_1); il.Emit(OpCodes.Newarr, typeof(object)); il.Emit(OpCodes.Stloc, fldArgs); il.Emit(OpCodes.Ldloc, fldArgs); il.Emit(OpCodes.Ldc_I4_0); il.Emit(OpCodes.Ldtoken, typeBuilder); il.Emit(OpCodes.Call, typeof(Type).GetMethod("GetTypeFromHandle")); il.Emit(OpCodes.Stelem_Ref); il.Emit(OpCodes.Ldloc, fldType); il.Emit(OpCodes.Ldstr, "EnsureComponentContextRegistryInitialized"); il.Emit(OpCodes.Callvirt, typeof(Type).GetMethod("GetMethod", new Type[] { typeof(string) })); il.Emit(OpCodes.Ldnull); il.Emit(OpCodes.Ldloc, fldArgs); il.Emit(OpCodes.Call, typeof(MethodBase).GetMethod("Invoke", new Type[] { typeof(object), typeof(object[]) })); il.Emit(OpCodes.Pop); il.Emit(OpCodes.Leave_S, methodEnd); il.BeginCatchBlock(typeof(Exception)); il.Emit(OpCodes.Call, typeof(Trace).GetMethod("WriteLine", new Type[] { typeof(object) })); il.EndExceptionBlock(); il.MarkLabel(methodEnd); il.Emit(OpCodes.Ret); return(typeBuilder.CreateType()); }
public TmpForNDimArr(LocalBuilder clb, Label tlabel, Label flabel) { this.clb = clb; this.tlabel = tlabel; this.flabel = flabel; }
private void AddReturn(Type ReturnType, ILGenerator il, MethodBuilder Meth) { // Place a dummy return value on the stack before we return. if (ReturnType == typeof(void)) { // There is nothing to place on the stack. } else if (ReturnType.IsPrimitive) { switch (System.Type.GetTypeCode(ReturnType)) { case TypeCode.Boolean: case TypeCode.Char: case TypeCode.Byte: case TypeCode.SByte: case TypeCode.Int16: case TypeCode.UInt16: case TypeCode.Int32: case TypeCode.UInt32: il.Emit(OpCodes.Ldc_I4_0); break; case TypeCode.Int64: case TypeCode.UInt64: il.Emit(OpCodes.Ldc_I4_0); il.Emit(OpCodes.Conv_I8); break; case TypeCode.Single: il.Emit(OpCodes.Ldc_R4, 0); break; case TypeCode.Double: il.Emit(OpCodes.Ldc_R4, 0); il.Emit(OpCodes.Conv_R8); break; default: // "TypeCode" does not include IntPtr, so special case it. if (ReturnType == typeof(IntPtr)) { il.Emit(OpCodes.Ldc_I4_0); } else { Contract.Assert(false, "Unexpected type for Primitive type."); } break; } } else if (ReturnType.IsValueType) { // Allocate stack space for the return value type. Zero-init. Meth.InitLocals = true; LocalBuilder ltRetVal = il.DeclareLocal(ReturnType); // Load the value class on the stack. il.Emit(OpCodes.Ldloc_S, ltRetVal); } else { // The return type is a normal type. il.Emit(OpCodes.Ldnull); } }
public virtual void Emit (OpCode opcode, LocalBuilder local) { throw new PlatformNotSupportedException (); }
private void EmitNullableCoalesce(BinaryExpression b) { Debug.Assert(b.Method == null); LocalBuilder loc = GetLocal(b.Left.Type); Label labIfNull = _ilg.DefineLabel(); Label labEnd = _ilg.DefineLabel(); EmitExpression(b.Left); _ilg.Emit(OpCodes.Stloc, loc); _ilg.Emit(OpCodes.Ldloca, loc); _ilg.EmitHasValue(b.Left.Type); _ilg.Emit(OpCodes.Brfalse, labIfNull); Type nnLeftType = b.Left.Type.GetNonNullableType(); if (b.Conversion != null) { Debug.Assert(b.Conversion.ParameterCount == 1); ParameterExpression p = b.Conversion.GetParameter(0); Debug.Assert(p.Type.IsAssignableFrom(b.Left.Type) || p.Type.IsAssignableFrom(nnLeftType)); // emit the delegate instance EmitLambdaExpression(b.Conversion); // emit argument if (!p.Type.IsAssignableFrom(b.Left.Type)) { _ilg.Emit(OpCodes.Ldloca, loc); _ilg.EmitGetValueOrDefault(b.Left.Type); } else { _ilg.Emit(OpCodes.Ldloc, loc); } // emit call to invoke _ilg.Emit(OpCodes.Callvirt, b.Conversion.Type.GetMethod("Invoke")); } else if (!TypeUtils.AreEquivalent(b.Type, nnLeftType)) { _ilg.Emit(OpCodes.Ldloca, loc); _ilg.EmitGetValueOrDefault(b.Left.Type); _ilg.EmitConvertToType(nnLeftType, b.Type, isChecked: true, locals: this); } else { _ilg.Emit(OpCodes.Ldloca, loc); _ilg.EmitGetValueOrDefault(b.Left.Type); } FreeLocal(loc); _ilg.Emit(OpCodes.Br, labEnd); _ilg.MarkLabel(labIfNull); EmitExpression(b.Right); if (!TypeUtils.AreEquivalent(b.Right.Type, b.Type)) { _ilg.EmitConvertToType(b.Right.Type, b.Type, isChecked: true, locals: this); } _ilg.MarkLabel(labEnd); }
public virtual void Emit(OpCode opcode, LocalBuilder local);
public void StoreLocal(LocalBuilder local) { Pop(local.LocalType); m_Generator.Emit(OpCodes.Stloc, local); }
internal ForState(LocalBuilder indexVar, Label beginLabel, Label testLabel, object end) { this.indexVar = indexVar; this.beginLabel = beginLabel; this.testLabel = testLabel; this.end = end; }
public bool CompareTo(int sign, Callback argGenerator) { Type active = this.Active; MethodInfo compareTo = active.GetMethod("CompareTo", new Type[] { active }); if (compareTo == null) { /* This gets a little tricky... * * There's a scenario where we might be trying to use CompareTo on an interface * which, while it doesn't explicitly implement CompareTo itself, is said to * extend IComparable indirectly. The implementation is implicitly passed off * to implementers... * * interface ISomeInterface : IComparable * { * void SomeMethod(); * } * * class SomeClass : ISomeInterface * { * void SomeMethod() { ... } * int CompareTo( object other ) { ... } * } * * In this case, calling ISomeInterface.GetMethod( "CompareTo" ) will return null. * * Bleh. */ Type[] ifaces = active.FindInterfaces(delegate(Type type, object obj) { return((type.IsGenericType) && (type.GetGenericTypeDefinition() == typeof(IComparable <>)) && (type.GetGenericArguments()[0].IsAssignableFrom(active))); }, null); if (ifaces.Length > 0) { compareTo = ifaces[0].GetMethod("CompareTo", new Type[] { active }); } else { ifaces = active.FindInterfaces(delegate(Type type, object obj) { return(type == typeof(IComparable)); }, null); if (ifaces.Length > 0) { compareTo = ifaces[0].GetMethod("CompareTo", new Type[] { active }); } } } if (compareTo == null) { return(false); } if (!active.IsValueType) { /* This object is a reference type, so we have to make it behave * * null.CompareTo( null ) = 0 * real.CompareTo( null ) = -1 * null.CompareTo( real ) = +1 * */ LocalBuilder aValue = AcquireTemp(active); LocalBuilder bValue = AcquireTemp(active); StoreLocal(aValue); argGenerator(); StoreLocal(bValue); /* if ( aValue == null ) * { * if ( bValue == null ) * v = 0; * else * v = +1; * } * else if ( bValue == null ) * { * v = -1; * } * else * { * v = aValue.CompareTo( bValue ); * } */ Label store = CreateLabel(); Label aNotNull = CreateLabel(); LoadLocal(aValue); BranchIfTrue(aNotNull); // if ( aValue == null ) { Label bNotNull = CreateLabel(); LoadLocal(bValue); BranchIfTrue(bNotNull); // if ( bValue == null ) { Load(0); Pop(typeof(int)); Branch(store); } MarkLabel(bNotNull); // else { Load(sign); Pop(typeof(int)); Branch(store); } } MarkLabel(aNotNull); // else { Label bNotNull = CreateLabel(); LoadLocal(bValue); BranchIfTrue(bNotNull); // bValue == null { Load(-sign); Pop(typeof(int)); Branch(store); } MarkLabel(bNotNull); // else { LoadLocal(aValue); BeginCall(compareTo); LoadLocal(bValue); ArgumentPushed(); FinishCall(); if (sign == -1) { Neg(); } } } MarkLabel(store); ReleaseTemp(aValue); ReleaseTemp(bValue); } else { BeginCall(compareTo); argGenerator(); ArgumentPushed(); FinishCall(); if (sign == -1) { Neg(); } } return(true); }
/// <summary> /// do foreach loop /// </summary> /// <param name="typeBuilder"></param> private static void MakeForeachMethod(TypeBuilder typeBuilder) { //定义一个传入参数为Int32[],返回值为Int32的方法 MethodBuilder methodBuilder = typeBuilder.DefineMethod("ForeachMethod", MethodAttributes.Public | MethodAttributes.Static, typeof(Int32), new Type[] { typeof(Int32[]) }); ILGenerator methodIL = methodBuilder.GetILGenerator(); //用来保存求和结果的局部变量 LocalBuilder sum = methodIL.DeclareLocal(typeof(Int32)); //foreach中的int i LocalBuilder i = methodIL.DeclareLocal(typeof(Int32)); //用来保存传入的数组 LocalBuilder ints = methodIL.DeclareLocal(typeof(Int32[])); //数组循环用临时变量 LocalBuilder index = methodIL.DeclareLocal(typeof(Int32)); Label compareLabel = methodIL.DefineLabel(); Label enterLoopLabel = methodIL.DefineLabel(); //int sum=0; methodIL.Emit(OpCodes.Ldc_I4_0); methodIL.Emit(OpCodes.Stloc_0); //ints=ints methodIL.Emit(OpCodes.Ldarg_0); methodIL.Emit(OpCodes.Stloc_2); //int index=0 methodIL.Emit(OpCodes.Ldc_I4_0); methodIL.Emit(OpCodes.Stloc_3); methodIL.Emit(OpCodes.Br, compareLabel); //定义一个标签,表示从下面开始进入循环体 methodIL.MarkLabel(enterLoopLabel); //其中Ldelem_I4用来加载一个数组中的Int32类型的元素 //加载i=ints[index] methodIL.Emit(OpCodes.Ldloc_2); methodIL.Emit(OpCodes.Ldloc_3); methodIL.Emit(OpCodes.Ldelem_I4); methodIL.Emit(OpCodes.Stloc_1); //sum+=i; methodIL.Emit(OpCodes.Ldloc_0); methodIL.Emit(OpCodes.Ldloc_1); methodIL.Emit(OpCodes.Add); methodIL.Emit(OpCodes.Stloc_0); //index++ methodIL.Emit(OpCodes.Ldloc_3); methodIL.Emit(OpCodes.Ldc_I4_1); methodIL.Emit(OpCodes.Add); methodIL.Emit(OpCodes.Stloc_3); //定义一个标签,表示从下面开始进入循环的比较 methodIL.MarkLabel(compareLabel); //index < ints.Length methodIL.Emit(OpCodes.Ldloc_3); methodIL.Emit(OpCodes.Ldloc_2); methodIL.Emit(OpCodes.Ldlen); methodIL.Emit(OpCodes.Conv_I4); methodIL.Emit(OpCodes.Clt); methodIL.Emit(OpCodes.Brtrue_S, enterLoopLabel); //return sum; methodIL.Emit(OpCodes.Ldloc_0); methodIL.Emit(OpCodes.Ret); }
private static void EventMain() { #region Init string name = "DynamicPublisher"; string fileName = name + ".dll"; AssemblyName asmName = new AssemblyName(name); AssemblyBuilder assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(asmName, AssemblyBuilderAccess.RunAndSave); ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule(name, fileName); #endregion #region RandGeneratedEventArgs TypeBuilder randGeneratedEventArgsTypeBuilder = moduleBuilder.DefineType("RandGeneratedEventArgs", TypeAttributes.Public, typeof(EventArgs)); #region Field FieldBuilder randField = randGeneratedEventArgsTypeBuilder.DefineField("_rand", typeof(Int32), FieldAttributes.Private); #endregion #region Property PropertyBuilder randProperty = randGeneratedEventArgsTypeBuilder.DefineProperty("Rand", PropertyAttributes.HasDefault, typeof(Int32), null); #region 定义属性Rand的get方法 //定义属性Rand的get方法 MethodBuilder getPropertyRandBuilder = randGeneratedEventArgsTypeBuilder.DefineMethod("get", MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.HideBySig, typeof(Int32), Type.EmptyTypes); //生成属性Rand的get方法的IL代码,即返回私有字段_a ILGenerator getRandIL = getPropertyRandBuilder.GetILGenerator(); getRandIL.Emit(OpCodes.Ldarg_0); getRandIL.Emit(OpCodes.Ldfld, randField); getRandIL.Emit(OpCodes.Ret); //设置属性A的get和set方法 randProperty.SetGetMethod(getPropertyRandBuilder); #endregion #endregion #region Ctor ConstructorBuilder constructorBuilder = randGeneratedEventArgsTypeBuilder.DefineConstructor(MethodAttributes.Public, CallingConventions.HasThis, new Type[] { typeof(Int32) }); ILGenerator ctorIL = constructorBuilder.GetILGenerator(); //加载参数1填充到私有字段_rand ctorIL.Emit(OpCodes.Ldarg_0); ctorIL.Emit(OpCodes.Ldarg_1); ctorIL.Emit(OpCodes.Stfld, randField); ctorIL.Emit(OpCodes.Ret); #endregion Type randGeneratedEventArgsType = randGeneratedEventArgsTypeBuilder.CreateType(); #endregion #region Publisher TypeBuilder publisherTypeBuilder = moduleBuilder.DefineType("Publisher", TypeAttributes.Public); Type eventType = typeof(EventHandler <>).MakeGenericType(randGeneratedEventArgsType); #region Field FieldBuilder randomField = publisherTypeBuilder.DefineField("random", typeof(Random), FieldAttributes.Private); FieldBuilder isStartField = publisherTypeBuilder.DefineField("isStart", typeof(Boolean), FieldAttributes.Private); //通过对自动生成的IL代码的仔细观察,发现系统自动生成了一个与事件同名的私有字段,用来在get set等方法中进行使用 FieldBuilder randGeneratedField = publisherTypeBuilder.DefineField("RandGenerated", eventType, FieldAttributes.Private); #endregion #region Ctor //注类似private Random random = new Random(DateTime.Now.Millisecond); 的字段初始化,需要在构造函数中进行 constructorBuilder = publisherTypeBuilder.DefineConstructor(MethodAttributes.Public, CallingConventions.HasThis, Type.EmptyTypes); ctorIL = constructorBuilder.GetILGenerator(); LocalBuilder dateTime = ctorIL.DeclareLocal(typeof(DateTime)); //加载参数0/false填充到私有字段isStart ctorIL.Emit(OpCodes.Ldarg_0); ctorIL.Emit(OpCodes.Ldc_I4_0); ctorIL.Emit(OpCodes.Stfld, isStartField); ctorIL.Emit(OpCodes.Ldarg_0); //获取DateTime.Now,这里由于DateTime是值类型,所以需要用Ldloca_S方法加载使用 ctorIL.Emit(OpCodes.Call, typeof(DateTime).GetMethod("get_Now", Type.EmptyTypes)); ctorIL.Emit(OpCodes.Stloc_0); ctorIL.Emit(OpCodes.Ldloca_S, dateTime); //获取DateTime.Millisecond,并用此初始化Random对象 ctorIL.Emit(OpCodes.Call, typeof(DateTime).GetMethod("get_Millisecond", Type.EmptyTypes)); ctorIL.Emit(OpCodes.Newobj, typeof(Random).GetConstructor(new Type[] { typeof(Int32) })); ctorIL.Emit(OpCodes.Stfld, randomField); //调用父类的无参构造函数 ctorIL.Emit(OpCodes.Ldarg_0); ctorIL.Emit(OpCodes.Call, typeof(Object).GetConstructor(Type.EmptyTypes)); ctorIL.Emit(OpCodes.Ret); #endregion #region Event //定义事件,事件的可访问性由和它相关的getset方法决定 EventBuilder randGeneratedEvent = publisherTypeBuilder.DefineEvent("RandGenerated", EventAttributes.None, eventType); MethodBuilder addEventBuilder = publisherTypeBuilder.DefineMethod("add_RandGenerated", MethodAttributes.Public, null, new Type[] { eventType }); //注意在我们使用事件时,使用的是+=操作,但在IL代码中并不是如此,应该使用Delegate.Combine方法 ILGenerator addEventIL = addEventBuilder.GetILGenerator(); addEventIL.Emit(OpCodes.Ldarg_0); addEventIL.Emit(OpCodes.Ldarg_0); addEventIL.Emit(OpCodes.Ldfld, randGeneratedField); addEventIL.Emit(OpCodes.Ldarg_1); addEventIL.Emit(OpCodes.Call, typeof(Delegate).GetMethod("Combine", new Type[] { eventType, eventType })); //返回的是Delegate类型,所以需要进行转换 addEventIL.Emit(OpCodes.Castclass, eventType); addEventIL.Emit(OpCodes.Stfld, randGeneratedField); randGeneratedEvent.SetAddOnMethod(addEventBuilder); MethodBuilder removeEventBuilder = publisherTypeBuilder.DefineMethod("remove_RandGenerated", MethodAttributes.Public, null, new Type[] { eventType }); //注意在我们使用事件时,使用的是-=操作,但在IL代码中并不是如此,应该使用Delegate.Remove方法 ILGenerator removeEventIL = removeEventBuilder.GetILGenerator(); removeEventIL.Emit(OpCodes.Ldarg_0); removeEventIL.Emit(OpCodes.Ldarg_0); removeEventIL.Emit(OpCodes.Ldfld, randGeneratedField); removeEventIL.Emit(OpCodes.Ldarg_1); removeEventIL.Emit(OpCodes.Call, typeof(Delegate).GetMethod("Remove", new Type[] { eventType, eventType })); //返回的是Delegate类型,所以需要进行转换 removeEventIL.Emit(OpCodes.Castclass, eventType); removeEventIL.Emit(OpCodes.Stfld, randGeneratedField); randGeneratedEvent.SetRemoveOnMethod(removeEventBuilder); #endregion #region Method #region Stop MethodBuilder stopBuilder = publisherTypeBuilder.DefineMethod("Stop", MethodAttributes.Public, null, Type.EmptyTypes); ILGenerator stopIL = stopBuilder.GetILGenerator(); stopIL.Emit(OpCodes.Ldarg_0); stopIL.Emit(OpCodes.Ldc_I4_0); stopIL.Emit(OpCodes.Stfld, isStartField); stopIL.Emit(OpCodes.Ret); #endregion #region RaiseRandGeneratedEvent MethodBuilder raiseRandGeneratedEventBuilder = publisherTypeBuilder.DefineMethod("RaiseRandGeneratedEvent", MethodAttributes.Private, null, new Type[] { typeof(Int32) }); ILGenerator raiseRandGeneratedEventIL = raiseRandGeneratedEventBuilder.GetILGenerator(); LocalBuilder temp = raiseRandGeneratedEventIL.DeclareLocal(eventType); LocalBuilder arg = raiseRandGeneratedEventIL.DeclareLocal(randGeneratedEventArgsType); Label returnLabel = raiseRandGeneratedEventIL.DefineLabel(); //EventHandler<RandGeneratedEventArgs> temp = RandGenerated; raiseRandGeneratedEventIL.Emit(OpCodes.Ldarg_0); raiseRandGeneratedEventIL.Emit(OpCodes.Ldfld, randGeneratedField); raiseRandGeneratedEventIL.Emit(OpCodes.Stloc_0); //if (temp == null) return raiseRandGeneratedEventIL.Emit(OpCodes.Ldloc_0); raiseRandGeneratedEventIL.Emit(OpCodes.Brfalse_S, returnLabel); //RandGeneratedEventArgs arg = new RandGeneratedEventArgs(rand); raiseRandGeneratedEventIL.Emit(OpCodes.Ldarg_1); raiseRandGeneratedEventIL.Emit(OpCodes.Newobj, randGeneratedEventArgsType.GetConstructor(new Type[] { typeof(Int32) })); raiseRandGeneratedEventIL.Emit(OpCodes.Stloc_1); //temp(this, arg); raiseRandGeneratedEventIL.Emit(OpCodes.Ldloc_0); raiseRandGeneratedEventIL.Emit(OpCodes.Ldarg_0); raiseRandGeneratedEventIL.Emit(OpCodes.Ldloc_1); raiseRandGeneratedEventIL.Emit(OpCodes.Callvirt, eventType.GetMethod("Invoke")); raiseRandGeneratedEventIL.MarkLabel(returnLabel); raiseRandGeneratedEventIL.Emit(OpCodes.Ret); #endregion #region OnRandGenerated MethodBuilder onRandGeneratedBuilder = publisherTypeBuilder.DefineMethod("OnRandGenerated", MethodAttributes.Virtual | MethodAttributes.Family | MethodAttributes.NewSlot, null, new Type[] { typeof(Int32) }); ILGenerator onRandGeneratedIL = onRandGeneratedBuilder.GetILGenerator(); onRandGeneratedIL.Emit(OpCodes.Ldarg_0); onRandGeneratedIL.Emit(OpCodes.Ldarg_1); onRandGeneratedIL.Emit(OpCodes.Call, raiseRandGeneratedEventBuilder); onRandGeneratedIL.Emit(OpCodes.Ret); #endregion #region GenerateRand MethodBuilder generateRandBuilder = publisherTypeBuilder.DefineMethod("GenerateRand", MethodAttributes.Private, null, Type.EmptyTypes); ILGenerator generateRandIL = generateRandBuilder.GetILGenerator(); Label enterLoopLable = generateRandIL.DefineLabel(); Label compareLable = generateRandIL.DefineLabel(); generateRandIL.Emit(OpCodes.Br_S, compareLable); generateRandIL.MarkLabel(enterLoopLable); //OnRandGenerated(random.Next(10000)); generateRandIL.Emit(OpCodes.Ldarg_0); generateRandIL.Emit(OpCodes.Ldarg_0); generateRandIL.Emit(OpCodes.Ldfld, randomField); generateRandIL.Emit(OpCodes.Ldc_I4, 10000); generateRandIL.Emit(OpCodes.Call, typeof(Random).GetMethod("Next", new Type[] { typeof(Int32) })); generateRandIL.Emit(OpCodes.Call, onRandGeneratedBuilder); //Thread.Sleep(1000); generateRandIL.Emit(OpCodes.Ldc_I4, 1000); generateRandIL.Emit(OpCodes.Call, typeof(System.Threading.Thread).GetMethod("Sleep", new Type[] { typeof(Int32) })); generateRandIL.MarkLabel(compareLable); generateRandIL.Emit(OpCodes.Ldarg_0); generateRandIL.Emit(OpCodes.Ldfld, isStartField); generateRandIL.Emit(OpCodes.Brtrue_S, enterLoopLable); generateRandIL.Emit(OpCodes.Ret); #endregion #region Start MethodBuilder startBuilder = publisherTypeBuilder.DefineMethod("Start", MethodAttributes.Public, null, Type.EmptyTypes); ILGenerator startIL = startBuilder.GetILGenerator(); returnLabel = startIL.DefineLabel(); //if (isStart) return startIL.Emit(OpCodes.Ldarg_0); startIL.Emit(OpCodes.Ldfld, isStartField); startIL.Emit(OpCodes.Brtrue_S, returnLabel); startIL.Emit(OpCodes.Ldarg_0); startIL.Emit(OpCodes.Call, generateRandBuilder); startIL.MarkLabel(returnLabel); startIL.Emit(OpCodes.Ret); #endregion #endregion Type publisherType = publisherTypeBuilder.CreateType(); #endregion //assemblyBuilder.Save(fileName); Publisher p = new Publisher(); p.RandGenerated += new EventHandler <RandGeneratedEventArgs>(p_RandGenerated); p.Start(); }
private void freeLocal(LocalBuilder l) { m_localPool.Add(l); }
static void EmitComputeBufferLoc(ILGenerator ilg, LocalBuilder bufLocal, int argnum) { ilg.Emit(OpCodes.Ldloc, bufLocal); ilg.Emit(OpCodes.Ldc_I4, argnum * VARIANT_SIZE); ilg.Emit(OpCodes.Add); }