private static Action <object, object> BuildFoister(FieldInfo field) { var methodName = "FieldFoister$"; if (field.IsStatic) { methodName += field.DeclaringType + "$"; } methodName += field.Name + "$" + Guid.NewGuid(); var dynamicMethod = new DynamicMethod(methodName, typeof(void), new[] { typeof(object), typeof(object) }, typeof(FieldsExtractor), true); using (var il = new GroboIL(dynamicMethod)) { if (!field.IsStatic) { il.Ldarg(0); il.Castclass(field.DeclaringType); } il.Ldarg(1); if (field.FieldType.IsValueType) { il.Unbox_Any(field.FieldType); } else { il.Castclass(field.FieldType); } il.Stfld(field); il.Ret(); } return((Action <object, object>)dynamicMethod.CreateDelegate(typeof(Action <object, object>))); }
private static Func <object, object, int> EmitCompareDelegate() { var method = new DynamicMethod(Guid.NewGuid().ToString(), typeof(int), new[] { typeof(object), typeof(object) }, typeof(string), true); var xsdDateTimeType = typeof(XmlReader).Assembly.GetTypes().FirstOrDefault(type => type.Name == "XsdDateTime"); if (xsdDateTimeType == null) { throw new InvalidOperationException("The type 'XsdDateTime' is not found"); } var compareMethod = xsdDateTimeType.GetMethod("Compare", BindingFlags.Static | BindingFlags.Public); if (compareMethod == null) { throw new InvalidOperationException("The method 'XsdDateTime.Compare' is not found"); } using (var il = new GroboIL(method)) { var strongBoxType = typeof(StrongBox <>).MakeGenericType(xsdDateTimeType); var valueField = strongBoxType.GetField("Value", BindingFlags.Instance | BindingFlags.Public); il.Ldarg(0); // stack: [arg0] il.Castclass(strongBoxType); // stack: [(StrongBox<XsdDateTime>)arg0] il.Ldfld(valueField); // stack: [((StrongBox<XsdDateTime>)arg0).Value] il.Ldarg(1); // stack: [((StrongBox<XsdDateTime>)arg0).Value, arg1] il.Castclass(strongBoxType); // stack: [((StrongBox<XsdDateTime>)arg0).Value, (StrongBox<XsdDateTime>)arg1] il.Ldfld(valueField); // stack: [((StrongBox<XsdDateTime>)arg0).Value, ((StrongBox<XsdDateTime>)arg1).Value] il.Call(compareMethod); // stack: [XsdDateTime.CompareTo(((StrongBox<XsdDateTime>)arg0).Value, ((StrongBox<XsdDateTime>)arg1).Value)] il.Ret(); } return((Func <object, object, int>)method.CreateDelegate(typeof(Func <object, object, int>))); }
private static Func <object, MethodBase, SignatureHelper, uint> BuildGetTokenFor() { var parameterTypes = new[] { typeof(object), typeof(MethodBase), typeof(SignatureHelper) }; var method = new DynamicMethod(Guid.NewGuid().ToString(), typeof(uint), parameterTypes, typeof(string), true); using (var il = new GroboIL(method)) { il.Ldarg(0); // stack: [scope] il.Castclass(dynamicScopeType); il.Ldarg(1); // stack: [scope, method] il.Castclass(runtimeMethodInfoType); // stack: [scope, (RuntimeMethodInfo)method] il.Ldarg(2); // stack: [scope, (RuntimeMethodInfo)method, signature] var constructor = varArgsMethodType.GetConstructor(BindingFlags.Instance | BindingFlags.NonPublic, null, new[] { runtimeMethodInfoType, typeof(SignatureHelper) }, null); if (constructor == null) { throw new MissingMethodException("VarArgsMethod", ".ctor"); } var getTokenForMethod = dynamicScopeType.GetMethod("GetTokenFor", BindingFlags.Instance | BindingFlags.NonPublic, null, new[] { varArgsMethodType }, null); if (getTokenForMethod == null) { throw new MissingMethodException("DynamicScope", "GetTokenFor"); } il.Newobj(constructor); // stack: [scope, new VarArgsMethod((RuntimeMethodInfo)method, signature)] il.Call(getTokenForMethod); // stack: [scope.GetTokenFor(new VarArgsMethod((RuntimeMethodInfo)method, signature))] il.Ret(); } return((Func <object, MethodBase, SignatureHelper, uint>)method.CreateDelegate(typeof(Func <object, MethodBase, SignatureHelper, uint>))); }
private WriterDelegate BuildWriter(Type type, bool ignoreCustomSerialization) { IntPtr writer = GetWriter(type, ignoreCustomSerialization); var dynamicMethod = new DynamicMethod(Guid.NewGuid().ToString(), typeof(void), new[] { typeof(object), typeof(bool), typeof(IntPtr), typeof(int).MakeByRefType(), typeof(WriterContext) }, module, true); using (var il = new GroboIL(dynamicMethod)) { il.Ldarg(0); // stack: [obj] if (type.IsValueType) { il.Unbox_Any(type); // stack: [(type)obj] } else { il.Castclass(type); // stack: [(type)obj] } il.Ldarg(1); // stack: [(type)obj, writeEmpty] il.Ldarg(2); // stack: [(type)obj, writeEmpty, result] il.Ldarg(3); // stack: [(type)obj, writeEmpty, result, ref index] il.Ldarg(4); // stack: [(type)obj, writeEmpty, result, ref index, context] il.Ldc_IntPtr(writer); il.Calli(CallingConventions.Standard, typeof(void), new[] { type, typeof(bool), typeof(IntPtr), typeof(int).MakeByRefType(), typeof(WriterContext) }); // writer.write<T>((type)obj, writeEmpty, result, ref index, context); stack: [] il.Ret(); } return((WriterDelegate)dynamicMethod.CreateDelegate(typeof(WriterDelegate))); }
private static KeyValuePair <Delegate, IntPtr> GetReader(ReaderMethodBuilderContext context, Type type) { var method = new DynamicMethod("Read_" + type.Name + "_AndCastToObject_" + Guid.NewGuid(), typeof(void), new[] { typeof(IntPtr), typeof(int).MakeByRefType(), typeof(object).MakeByRefType(), typeof(ReaderContext) }, context.Context.Module, true); using (var il = new GroboIL(method)) { il.Ldarg(2); // stack: [ref result] il.Ldarg(0); // stack: [ref result, data] il.Ldarg(1); // stack: [ref result, data, ref index] var value = il.DeclareLocal(type); il.Ldloca(value); // stack: [ref result, data, ref index, ref value] il.Ldarg(3); // stack: [ref result, data, ref index, ref value, context] ReaderMethodBuilderContext.CallReader(il, type, context.Context); il.Ldloc(value); // stack: [ref result, value] if (type.IsValueType) { il.Box(type); // stack: [ref result, (object)value] } else { il.Castclass(type); } il.Stind(typeof(object)); // result = (object)value il.Ret(); } var @delegate = method.CreateDelegate(typeof(ReaderDelegate)); return(new KeyValuePair <Delegate, IntPtr>(@delegate, GroBufHelpers.ExtractDynamicMethodPointer(method))); }
private static KeyValuePair <Delegate, IntPtr> GetWriter(WriterMethodBuilderContext context, Type type) { var method = new DynamicMethod("CastTo_" + type.Name + "_AndWrite_" + Guid.NewGuid(), typeof(void), new[] { typeof(object), typeof(bool), typeof(IntPtr), typeof(int).MakeByRefType(), typeof(WriterContext) }, context.Context.Module, true); using (var il = new GroboIL(method)) { il.Ldarg(0); // stack: [obj] if (type.IsValueType) { il.Unbox_Any(type); // stack: [(type)obj] } else { il.Castclass(type); // stack: [(type)obj] } il.Ldarg(1); // stack: [(type)obj, writeEmpty] il.Ldarg(2); // stack: [(type)obj, writeEmpty, result] il.Ldarg(3); // stack: [(type)obj, writeEmpty, result, ref index] il.Ldarg(4); // stack: [(type)obj, writeEmpty, result, ref index, context] context.CallWriter(il, type); il.Ret(); } var @delegate = method.CreateDelegate(typeof(WriterDelegate <object>)); return(new KeyValuePair <Delegate, IntPtr>(@delegate, GroBufHelpers.ExtractDynamicMethodPointer(method))); }
public static Func <Dictionary <string, object>, object> GenerateMethod(Type type) { var da = AppDomain.CurrentDomain.DefineDynamicAssembly( new AssemblyName("dyn"), // call it whatever you want AssemblyBuilderAccess.RunAndSave); var dm = da.DefineDynamicModule("dyn_mod", "dyn.dll"); var dt = dm.DefineType("dyn_type"); var emiter = Emit <Func <int> > .NewDynamicMethod("MyMethod"); var method = dt.DefineMethod( "Foo", MethodAttributes.Public | MethodAttributes.Static, typeof(object), new[] { typeof(Dictionary <string, object>) }); method.DefineParameter(1, ParameterAttributes.None, "dictionary"); using (var il = new GroboIL(method)) { var target = il.DeclareLocal(type); var value = il.DeclareLocal(typeof(object)); il.Newobj(type.GetConstructor(Type.EmptyTypes)); // [Person] il.Stloc(target); // [] foreach (var property in type.GetProperties()) { var label = il.DefineLabel("ifLabel"); il.Ldarg(0); // [Dictionary<String, Object>] il.Ldstr(property.Name); // [Dictionary<String, Object>, String] il.Ldloca(value); // [Dictionary<String, Object>, String, Object&] il.Call(typeof(Dictionary <string, object>) .GetMethod("TryGetValue")); // [Boolean] il.Brfalse(label); // [] il.Ldloc(target); // [Person] il.Ldloc(value); // [Person, Object] il.Castclass(typeof(string)); // [Dictionary<String, Object>, String] il.Call(property.GetSetMethod(true)); // [] il.MarkLabel(label); } il.Ldloc(target); il.Ret(); Console.WriteLine(il.GetILCode()); } dt.CreateType(); da.Save("dyn.dll"); return((dic) => dt.GetMethod("Foo").Invoke(null, new object[] { dic })); }
private SizeCounterDelegate BuildCounter(Type type, bool ignoreCustomSerialization) { IntPtr counter = GetCounter(type, ignoreCustomSerialization); var dynamicMethod = new DynamicMethod(Guid.NewGuid().ToString(), typeof(int), new[] { typeof(object), typeof(bool), typeof(WriterContext) }, GetType(), true); using (var il = new GroboIL(dynamicMethod)) { il.Ldarg(0); // stack: [obj] if (type.IsValueType) { il.Unbox_Any(type); // stack: [(type)obj] } else { il.Castclass(type); // stack: [(type)obj] } il.Ldarg(1); // stack: [(type)obj, writeEmpty] il.Ldarg(2); // stack: [(type)obj, writeEmpty, context] il.Ldc_IntPtr(counter); // stack: [(type)obj, writeEmpty, context, counter] il.Calli(CallingConventions.Standard, typeof(int), new[] { type, typeof(bool), typeof(WriterContext) }); // counter((type)obj, writeEmpty, context); stack: [] il.Ret(); } return((SizeCounterDelegate)dynamicMethod.CreateDelegate(typeof(SizeCounterDelegate))); }
private static Func <Type, bool> BuildIsATypeBuilderInstantiationChecker() { var dynamicMethod = new DynamicMethod(Guid.NewGuid().ToString(), typeof(bool), new[] { typeof(Type) }, typeof(ReflectionExtensions), true); using (var il = new GroboIL(dynamicMethod)) { il.Ldarg(0); il.Castclass(typeBuilderInstantiationType); il.Ldnull(); il.Cgt(true); il.Ret(); } return((Func <Type, bool>)dynamicMethod.CreateDelegate(typeof(Func <Type, bool>))); }
public void GetReadILCode(PropertyData prop, BinaryStruct currentStruct, GroboIL il, GroboIL.Local binaryStruct, GroboIL.Local buffer, GroboIL.Local result, GroboIL.Local typeSize, GroboIL.Local offset, bool listValue) { var exitLabel = il.DefineLabel("exit"); BinaryStruct.ReadObjectNull(il, exitLabel, buffer, offset, typeSize); var len = il.DeclareLocal(typeof(int)); il.Ldloc(buffer); il.Ldloc(offset); il.Call(readBitConverterMethodInfo); il.Stloc(len); BinaryStruct.WriteOffsetAppend(il, offset, 4); if (!listValue) { il.Ldloc(result); il.Ldarg(1); } else { il.Ldloc(binaryStruct); } il.Call(codingMethodInfo); il.Castclass(typeof(UTF8Encoding)); il.Ldloc(buffer); il.Ldloc(offset); il.Ldloc(len); il.Call(currentStruct.Coding.GetType().GetMethod("GetString", new Type[] { typeof(byte[]), typeof(int), typeof(int) }), isVirtual: true); if (!listValue) { il.Call(prop.Setter); } else { il.Stloc(result); } BinaryStruct.WriteOffsetAppend(il, offset, len); il.MarkLabel(exitLabel); }
private static void BuildFactoryByDynamicILGenerator() { var method = new DynamicMethod(Guid.NewGuid().ToString(), typeof(object), new[] { typeof(ILGenerator) }, typeof(string), true); using (var il = new GroboIL(method)) { il.Ldarg(0); il.Castclass(dynamicILGeneratorType); var constructor = dynamicResolverType.GetConstructor(BindingFlags.Instance | BindingFlags.NonPublic, null, new[] { dynamicILGeneratorType }, null); if (constructor == null) { throw new MissingMethodException("DynamicResolver", ".ctor"); } il.Newobj(constructor); il.Ret(); } factoryByDynamicILGenerator = (Func <ILGenerator, object>)method.CreateDelegate(typeof(Func <ILGenerator, object>)); }
private static void BuildGetRawEHInfoDelegate() { var method = new DynamicMethod(Guid.NewGuid().ToString(), typeof(byte[]), new[] { typeof(object) }, typeof(string), true); using (var il = new GroboIL(method)) { il.Ldarg(0); il.Castclass(dynamicResolverType); var getRawEHInfoMethod = dynamicResolverType.GetMethod("GetRawEHInfo", BindingFlags.Instance | BindingFlags.NonPublic); if (getRawEHInfoMethod == null) { throw new MissingMethodException("DynamicResolver", "GetRawEHInfo"); } il.Call(getRawEHInfoMethod); il.Ret(); } getRawEHInfoDelegate = (Func <object, byte[]>)method.CreateDelegate(typeof(Func <object, byte[]>)); }
private static Func <DynamicMethod, object, GrEmit.Utils.DynamicILInfo> BuildGetDynamicILInfo() { var method = new DynamicMethod(Guid.NewGuid().ToString(), typeof(GrEmit.Utils.DynamicILInfo), new[] { typeof(DynamicMethod), typeof(object) }, typeof(string), true); using (var il = new GroboIL(method)) { il.Ldarg(0); // stack: [dynamicMethod] il.Ldarg(1); // stack: [dynamicMethod, scope] il.Castclass(dynamicScopeType); var getDynamicILInfoMethod = typeof(DynamicMethod).GetMethod("GetDynamicILInfo", BindingFlags.Instance | BindingFlags.NonPublic); if (getDynamicILInfoMethod == null) { throw new MissingMethodException("DynamicMethod", "GetDynamicILInfo"); } il.Call(getDynamicILInfoMethod); // stack: [dynamicMethod.GetDynamicILInfo(scope)] il.Ret(); } return((Func <DynamicMethod, object, GrEmit.Utils.DynamicILInfo>)method.CreateDelegate(typeof(Func <DynamicMethod, object, GrEmit.Utils.DynamicILInfo>))); }
private static Func <object, int, object> BuildItemGetter() { var method = new DynamicMethod(Guid.NewGuid().ToString(), typeof(object), new[] { typeof(object), typeof(int) }, typeof(string), true); using (var il = new GroboIL(method)) { il.Ldarg(0); // stack: [scope] il.Castclass(dynamicScopeType); il.Ldarg(1); // stack: [scope, token] var property = dynamicScopeType.GetProperty("Item", BindingFlags.Instance | BindingFlags.NonPublic); if (property == null) { throw new MissingMethodException("DynamicScope", "get_Item"); } var getter = property.GetGetMethod(true); il.Call(getter); // stack: [scope[this]] il.Ret(); } return((Func <object, int, object>)method.CreateDelegate(typeof(Func <object, int, object>))); }
private void ProcessParameter(ParameterInfo parameterInfo, GroboIL il, int parameterMarker) { var parameterType = parameterInfo.ParameterType; if (parameterMarker != -1) { il.Ldarg(2); //parameters il.Ldc_I4(parameterMarker); il.Ldelem(typeof(object)); if (parameterType.IsValueType) { if (!IsNullable(parameterType)) { EmitCrashIfValueIsNull(il); } il.Unbox_Any(parameterType); } else { il.Castclass(parameterType); } } else { il.Ldarg(0); //container -> this for methods il.Ldarg(1); //arg0: context if (parameterType.IsArray) { ProcessArray(il, parameterType.GetElementType()); } else if (parameterType.IsGenericType && parameterType.GetGenericTypeDefinition() == typeof(IEnumerable <>)) { ProcessArray(il, parameterType.GetGenericArguments()[0]); } else { ProcessNonArray(parameterInfo, il, parameterType); } } }
private static void BuildGetEHInfoDelegate() { var parameterTypes = new[] { typeof(object), typeof(int), typeof(void *) }; var method = new DynamicMethod(Guid.NewGuid().ToString(), typeof(void), parameterTypes, typeof(string), true); using (var il = new GroboIL(method)) { il.Ldarg(0); il.Castclass(dynamicResolverType); il.Ldarg(1); il.Ldarg(2); var getEHInfoMethod = dynamicResolverType.GetMethod("GetEHInfo", BindingFlags.Instance | BindingFlags.NonPublic); if (getEHInfoMethod == null) { throw new MissingMethodException("DynamicResolver", "GetEHInfo"); } il.Call(getEHInfoMethod); il.Ret(); } getEHInfoDelegate = (GetEHInfoDelegate)method.CreateDelegate(typeof(GetEHInfoDelegate)); }
private static void BuildChildren(TypeBuilder typeBuilder, int n, Context context) { var property = typeBuilder.DefineProperty("Children", PropertyAttributes.None, typeof(IEnumerable <MethodCallNode>), Type.EmptyTypes); var getter = typeBuilder.DefineMethod("get_Children", MethodAttributes.Public | MethodAttributes.Virtual, CallingConventions.HasThis, typeof(IEnumerable <MethodCallNode>), Type.EmptyTypes); using (var il = new GroboIL(getter)) { il.Ldc_I4(n); // stack: [n] il.Newarr(typeof(MethodCallNode)); // stack: [new int[n] -> values] for (int i = 0; i < n; ++i) { il.Dup(); // stack: [values, values] il.Ldc_I4(i); // stack: [values, values, i] il.Ldarg(0); // stack: [values, values, i, this] il.Ldfld(context.values[i]); // stack: [values, values, i, this.values_{i}] il.Stelem(typeof(MethodCallNode)); // values[i] = this.values_{i}; stack: [values] } il.Castclass(typeof(IEnumerable <MethodCallNode>)); il.Ret(); } property.SetGetMethod(getter); typeBuilder.DefineMethodOverride(getter, typeof(MethodCallNodeEdges).GetProperty(property.Name, BindingFlags.Public | BindingFlags.Instance).GetGetMethod()); }
public static void EmitConstructionOfType(Type type, GroboIL il) { ConstructorInfo constructor = type.GetConstructor(Type.EmptyTypes); if (constructor != null) { il.Newobj(constructor); } else { il.Ldtoken(type); il.Call(getTypeFromHandle); il.Call(getUninitializedObject); if (type.IsValueType) { il.Unbox_Any(type); } else { il.Castclass(type); } } }
private Func <object> BuildConstants(Type type, ClosureSubstituter closureSubstituter) { var method = new DynamicMethod(Guid.NewGuid().ToString(), typeof(object), new[] { typeof(object[]) }, typeof(ExpressionClosureBuilder), true); var root = Expression.Parameter(type); var consts = new object[hashtable.Count]; using (var il = new GroboIL(method)) { il.Newobj(type.GetConstructor(Type.EmptyTypes)); // stack: [new Constants()] var result = il.DeclareLocal(type, "result"); il.Stloc(result); // result = new Constants(); stack: [] int index = 0; foreach (DictionaryEntry entry in hashtable) { var pair = (Tuple <Type, object>)entry.Key; var constType = pair.Item1; consts[index] = pair.Item2 is Expression?closureSubstituter.Visit((Expression)pair.Item2) : pair.Item2; var fieldAccessor = constantsBuilder.MakeAccess(root, ((int?)entry.Value).Value); var pathToField = new List <FieldInfo>(); while (fieldAccessor.NodeType != ExpressionType.Parameter) { var memberExpression = (MemberExpression)fieldAccessor; pathToField.Add((FieldInfo)memberExpression.Member); fieldAccessor = memberExpression.Expression; } pathToField.Reverse(); il.Ldloc(result); for (int i = 0; i < pathToField.Count - 1; ++i) { il.Ldflda(pathToField[i]); // stack: [ref result.field] il.Dup(); // stack: [ref result.field, ref result.field] var fieldType = pathToField[i].FieldType; il.Ldind(fieldType); // stack: [ref result.field, result.field] var notNullLabel = il.DefineLabel("notNull"); il.Brtrue(notNullLabel); // if(result.field != null) goto notNull; stack: [ref result.field] il.Dup(); // stack: [ref result.field, ref result.field] il.Newobj(fieldType.GetConstructor(Type.EmptyTypes)); // stack: [ref result.field, ref result.field, new field()] il.Stind(fieldType); // result.field = new field(); stack: [ref result.field] il.MarkLabel(notNullLabel); il.Ldind(fieldType); // stack: [result.field] } il.Ldarg(0); // stack: [path, args] il.Ldc_I4(index++); // stack: [path, args, index] il.Ldelem(typeof(object)); // stack: [path, args[index]] var field = pathToField.Last(); if (!constType.IsValueType) { il.Castclass(field.FieldType); // stack: [path, (FieldType)args[index]] } else { il.Unbox_Any(constType); if (field.FieldType != constType) { var constructor = field.FieldType.GetConstructor(new[] { constType }); if (constructor == null) { throw new InvalidOperationException(string.Format("Missing constructor of type '{0}' with parameter of type '{1}'", Formatter.Format(field.FieldType), Formatter.Format(constType))); } il.Newobj(constructor); } } il.Stfld(field); // path.field = (FieldType)args[index]; stack: [] } il.Ldloc(result); il.Ret(); } var func = (Func <object[], object>)method.CreateDelegate(typeof(Func <object[], object>)); return(() => func(consts)); }
private static Type BuildTypeInternal(Type type) { var parentType = typeof(ValidationResultTreeNode); var properties = type.GetProperties(BindingFlags.Instance | BindingFlags.Public); var typeBuilder = module.DefineType(type.Name + "_" + id++, TypeAttributes.Class | TypeAttributes.Public, parentType); typesBeingBuilt[type] = typeBuilder; var constructor = typeBuilder.DefineConstructor(MethodAttributes.Public, CallingConventions.HasThis, new[] { parentType }); using (var il = new GroboIL(constructor)) { il.Ldarg(0); // stack: [this] il.Ldarg(1); // stack: [this, parent] var baseConstructor = parentType.GetConstructor(BindingFlags.Instance | BindingFlags.NonPublic, null, new[] { parentType }, null); il.Call(baseConstructor); // base(parent); stack: [] il.Ret(); } var fields = new Dictionary <string, FieldBuilder>(); foreach (var property in properties) { var propertyType = property.PropertyType; Type fieldType; if (propertyType.IsArray) { fieldType = typeof(ValidationResultTreeArrayNode <>).MakeGenericType(BuildType(propertyType.GetElementType())); } else if (propertyType.IsDictionary() || propertyType == typeof(Hashtable)) { fieldType = typeof(ValidationResultTreeUniversalNode); } else { fieldType = BuildType(propertyType, true); } var field = typeBuilder.DefineField(property.Name, fieldType, FieldAttributes.Public); fields.Add(property.Name, field); } var getChildrenMethod = parentType.GetMethod("GetChildren", BindingFlags.Instance | BindingFlags.NonPublic); var getChildrenMethodBuilder = typeBuilder.DefineMethod(getChildrenMethod.Name, MethodAttributes.Public | MethodAttributes.Virtual, typeof(IEnumerable <KeyValuePair <object, ValidationResultTreeNode> >), Type.EmptyTypes); using (var il = new GroboIL(getChildrenMethodBuilder)) { var listType = typeof(List <KeyValuePair <object, ValidationResultTreeNode> >); var addMethod = listType.GetMethod("Add", new[] { typeof(KeyValuePair <object, ValidationResultTreeNode>) }); var itemConstructor = typeof(KeyValuePair <object, ValidationResultTreeNode>).GetConstructor(new[] { typeof(object), parentType }); var list = il.DeclareLocal(listType); il.Newobj(listType.GetConstructor(Type.EmptyTypes)); // stack: [new List<>()] il.Stloc(list); // list = new List<>(); stack: [] foreach (var field in fields.Values) { il.Ldarg(0); // stack: [this] il.Ldfld(field); // stack: [this.field] var nextLabel = il.DefineLabel("next"); il.Brfalse(nextLabel); // if(this.field == null) goto next; stack: [] il.Ldloc(list); // stack: [list] il.Ldstr(field.Name); // stack: [list, field.Name] il.Ldarg(0); // stack: [list, field.Name, this] il.Ldfld(field); // stack: [list, field.Name, this.field] il.Newobj(itemConstructor); // stack: [list, new KeyValuePair<object, ValidationResultTreeNode>(field.Name, this.field)] il.Call(addMethod); // list.Add(new KeyValuePair<object, ValidationResultTreeNode>(field.Name, this.field)); stack: [] il.MarkLabel(nextLabel); } il.Ldloc(list); il.Ret(); } typeBuilder.DefineMethodOverride(getChildrenMethodBuilder, getChildrenMethod); var traverseEdgeMethod = parentType.GetMethod("TraverseEdge", BindingFlags.Instance | BindingFlags.NonPublic); var traverseEdgeMethodBuilder = typeBuilder.DefineMethod(traverseEdgeMethod.Name, MethodAttributes.Public | MethodAttributes.Virtual, parentType, new[] { typeof(Expression) }); using (var il = new GroboIL(traverseEdgeMethodBuilder)) { il.Ldarg(1); // stack: [edge] il.Castclass(typeof(MemberExpression)); // stack: [(MemberExpression)edge] il.Call(HackHelpers.GetProp <MemberExpression>(x => x.Member).GetGetMethod()); // stack: [((MemberExpresion)edge).Member] il.Call(HackHelpers.GetProp <MemberInfo>(x => x.Name).GetGetMethod()); // stack: [((MemberExpresion)edge).Member.Name] var member = il.DeclareLocal(typeof(string)); il.Stloc(member); foreach (var property in properties) { il.Ldstr(property.Name); // stack: [property.Name] il.Ldloc(member); // stack: [property.Name, member] il.Call(typeof(string).GetMethod("op_Equality", BindingFlags.Static | BindingFlags.Public)); var nextLabel = il.DefineLabel("next"); il.Brfalse(nextLabel); // if(property.Name != member) goto next; stack: [] il.Ldarg(0); // stack: [this] il.Ldfld(fields[property.Name]); // stack: [this.field] il.Ret(); // return this.field; il.MarkLabel(nextLabel); } il.Ldnull(); il.Ret(); } typeBuilder.DefineMethodOverride(traverseEdgeMethodBuilder, traverseEdgeMethod); var result = typeBuilder.CreateTypeInfo(); typesBeingBuilt[type] = null; return(result); }
public void BuildReader(ReaderTypeBuilderContext readerTypeBuilderContext) { var method = new DynamicMethod("Read_" + Type.Name + "_" + Guid.NewGuid(), typeof(void), new[] { typeof(IntPtr), typeof(int).MakeByRefType(), Type.MakeByRefType(), typeof(ReaderContext) }, readerTypeBuilderContext.Module, true); readerTypeBuilderContext.SetReaderMethod(Type, method); using (var il = new GroboIL(method)) { var context = new ReaderMethodBuilderContext(readerTypeBuilderContext, il, !Type.IsValueType && IsReference); ReadTypeCodeAndCheck(context); // Read TypeCode and check if (!Type.IsValueType && IsReference) { // Read reference context.LoadContext(); // stack: [context] il.Ldfld(ReaderContext.ObjectsField); // stack: [context.objects] var notReadLabel = il.DefineLabel("notRead"); il.Brfalse(notReadLabel); context.LoadIndex(); // stack: [external index] context.LoadContext(); // stack: [external index, context] il.Ldfld(ReaderContext.StartField); // stack: [external index, context.start] il.Sub(); // stack: [external index - context.start] il.Stloc(context.Index); // index = external index - context.start; stack: [] context.LoadContext(); // stack: [context] il.Ldfld(ReaderContext.ObjectsField); // stack: [context.objects] il.Ldloc(context.Index); // stack: [context.objects, index] var obj = il.DeclareLocal(typeof(object)); il.Ldloca(obj); object dummy; il.Call(HackHelpers.GetMethodDefinition <Dictionary <int, object> >(dict => dict.TryGetValue(0, out dummy))); // stack: [context.objects.TryGetValue(index, out obj)] il.Brfalse(notReadLabel); // if(!context.objects.TryGetValue(index, out obj)) goto notRead; context.LoadResultByRef(); // stack: [ref result] il.Ldloc(obj); // stack: [ref result, obj] il.Castclass(Type); // stack: [ref result, (Type)obj] il.Stind(Type); // result = (Type)obj; stack: [] context.IncreaseIndexBy1(); // Skip type code context.SkipValue(); // Skip value - it has already been read il.Ret(); il.MarkLabel(notReadLabel); il.Ldloc(context.TypeCode); // stack: [typeCode] il.Ldc_I4((int)GroBufTypeCode.Reference); // stack: [typeCode, GroBufTypeCode.Reference] var readUsualLabel = il.DefineLabel("readUsual"); il.Bne_Un(readUsualLabel); // if(typeCode != GroBufTypeCode.Reference) goto readUsual; stack: [] context.LoadContext(); // stack: [context] il.Ldfld(ReaderContext.ObjectsField); // stack: [context.objects] var objectsIsNotNullLabel = il.DefineLabel("objectsIsNotNull"); il.Brtrue(objectsIsNotNullLabel); // if(context.objects != null) goto objectsIsNotNull; stack: [context.objects] il.Ldstr("Reference is not valid at this point"); il.Newobj(typeof(DataCorruptedException).GetConstructor(new[] { typeof(string) })); il.Throw(); il.MarkLabel(objectsIsNotNullLabel); context.IncreaseIndexBy1(); // index = index + 1; stack: [] il.Ldc_I4(4); context.AssertLength(); context.GoToCurrentLocation(); var reference = il.DeclareLocal(typeof(int)); il.Ldind(typeof(int)); // stack: [*(int*)data[index]] il.Stloc(reference); // reference = *(int*)data[index]; stack: [] context.IncreaseIndexBy4(); // index = index + 4; stack: [] il.Ldloc(context.Index); // stack: [index] il.Ldloc(reference); // stack: [index, reference] var goodReferenceLabel = il.DefineLabel("goodReference"); il.Bgt(goodReferenceLabel, false); // if(index > reference) goto goodReference; stack: [] il.Ldstr("Bad reference"); il.Newobj(typeof(DataCorruptedException).GetConstructor(new[] { typeof(string) })); il.Throw(); il.MarkLabel(goodReferenceLabel); context.LoadContext(); // stack: [context] il.Ldfld(ReaderContext.ObjectsField); // stack: [context.objects] il.Ldloc(reference); // stack: [context.objects, reference] il.Ldloca(obj); // stack: [context.objects, reference, ref obj] il.Call(HackHelpers.GetMethodDefinition <Dictionary <int, object> >(dict => dict.TryGetValue(0, out dummy))); // stack: [context.objects.TryGetValue(reference, out obj)] var readObjectLabel = il.DefineLabel("readObject"); il.Brfalse(readObjectLabel); // if(!context.objects.TryGetValue(reference, out obj)) goto readObjects; stack: [] context.LoadResultByRef(); // stack: [ref result] il.Ldloc(obj); // stack: [ref result, obj] il.Castclass(Type); // stack: [ref result, (Type)obj] il.Stind(Type); // result = (Type)obj; stack: [] il.Ret(); il.MarkLabel(readObjectLabel); // Referenced object has not been read - this means that the object reference belongs to is a property that had been deleted context.LoadData(); // stack: [data] il.Ldloc(reference); // stack: [data, reference] context.LoadContext(); // stack: [data, reference, context] il.Ldfld(ReaderContext.StartField); // stack: [data, reference, context.start] il.Add(); // stack: [data, reference + context.start] il.Stloc(reference); // reference += context.start; stack: [data] il.Ldloca(reference); // stack: [data, ref reference] context.LoadResultByRef(); // stack: [data, ref reference, ref result] context.LoadContext(); // stack: [data, ref reference, ref result, context] context.CallReader(Type); il.Ret(); il.MarkLabel(readUsualLabel); } ReadNotEmpty(context); // Read obj il.Ret(); } var @delegate = method.CreateDelegate(typeof(ReaderDelegate <>).MakeGenericType(Type)); var pointer = GroBufHelpers.ExtractDynamicMethodPointer(method); readerTypeBuilderContext.SetReaderPointer(Type, pointer, @delegate); }
private static MethodBuilder GenerateOverloadedMethodDelegate(MethodInfo methodToIntercept, TypeBuilder typeBuilder, FieldInfo concrete) { // Define the method var method = typeBuilder.DefineMethod(methodToIntercept.Name + "-Delegate", MethodAttributes.Private | MethodAttributes.HideBySig, methodToIntercept.ReturnType, new[] { typeof(ParamInfo[]) }); SetupGenericMethodArguments(methodToIntercept, method); // Local for each out/ref parameter var parameters = methodToIntercept.GetParameters(); var locals = new Dictionary <string, Local>(); using (var il = new GroboIL(method)) { foreach (ParameterInfo parameter in parameters) { if (parameter.IsOut || parameter.ParameterType.IsByRef) { locals.Add(parameter.Name, il.DeclareLocal(parameter.ParameterType.GetElementType(), parameter.Name)); } } var paramInfoType = typeof(ParamInfo); var paramInfoGetValue = paramInfoType.GetProperty("Value").GetGetMethod(); // Initialize out parameters to default values for (var i = 0; i < parameters.Length; i++) { if (parameters[i].ParameterType.IsByRef && !parameters[i].IsOut) { il.Ldarg(1); il.Ldc_I4(i); il.Ldelem(paramInfoType); il.Call(paramInfoGetValue); if (parameters[i].ParameterType.GetElementType().IsValueType) { il.Unbox_Any(parameters[i].ParameterType.GetElementType()); } else { il.Castclass(parameters[i].ParameterType.GetElementType()); } il.Stloc(locals[parameters[i].Name]); } } // Load target il.Ldarg(0); il.Ldfld(concrete); // Push call values onto stack for (var i = 0; i < parameters.Length; i++) { if (parameters[i].IsOut || parameters[i].ParameterType.IsByRef) { il.Ldloca(locals[parameters[i].Name]); } else { il.Ldarg(1); il.Ldc_I4(i); il.Ldelem(paramInfoType); il.Call(paramInfoGetValue); if (parameters[i].ParameterType.IsValueType || parameters[i].ParameterType.IsGenericParameter) { il.Unbox_Any(parameters[i].ParameterType); } else { il.Castclass(parameters[i].ParameterType); } } } // Call intercepted method il.Call(methodToIntercept); var paramInfoSetValue = paramInfoType.GetProperty("Value").GetSetMethod(); // Copy out/ref parameter values back into passed-in parameters array for (var i = 0; i < parameters.Length; i++) { if (parameters[i].IsOut || parameters[i].ParameterType.IsByRef) { il.Ldarg(1); il.Ldc_I4(i); il.Ldelem(paramInfoType); il.Ldloc(locals[parameters[i].Name]); if (parameters[i].ParameterType.GetElementType().IsValueType) { il.Box(parameters[i].ParameterType.GetElementType()); } il.Call(paramInfoSetValue); } } il.Ret(); LogIlCode(il); } return(method); }