/// <summary> /// 如果是值类型, 则将值类型装箱后推送到计算栈 /// </summary> /// <param name="il"></param> public static void BoxIfNeed(this ILGenerator il, Type type) { if (type.IsValueType) { il.Box(type); } }
/// <summary> /// Performs a boxing operation if the given type is a value type. /// </summary> /// <param name="il">The instance of <see cref="ILGenerator"/>.</param> /// <param name="type">The type.</param> /// <returns>The instance of <see cref="ILGenerator"/>.</returns> public static ILGenerator BoxIfNeeded(this ILGenerator il, Type type) { if (type.IsValueType) { il.Box(type); } return(il); }
public static ILGenerator BoxIfNeeded(this ILGenerator il, System.Type type) { if (type.GetTypeInfo().IsValueType) { il.Box(type); } return(il); }
/// <summary> /// /// </summary> /// <param name="il"></param> /// <param name="source"></param> /// <param name="destination"></param> /// <returns></returns> public static ILGenerator Convert(this ILGenerator il, Type source, Type destination) { if (source == null) { throw new ArgumentNullException("source"); } if (destination == null) { throw new ArgumentNullException("destination"); } if (source == destination) { return(il); } if (source == typeof(Object) && destination.IsValueType) { return(il.Unbox_Any(destination)); } if (source.IsValueType && destination == typeof(Object)) { return(il.Box(destination)); } // if (source.IsAssignableFrom(destination)) return this; // --> it doesn't work for int? -> int, cause int is assignable from int? var converter = LookUpConverter(source, destination); if (converter != null) // not so beauty, but it's enough for internal code { // todo. implement invariant culture here if (converter is ConstructorInfo) { return(il.Newobj((ConstructorInfo)converter)); } // note the ClassCastException expected below in near future :) return(converter.IsVirtual ? il.Callvirt((MethodInfo)converter) : il.Call((MethodInfo)converter)); } Func <ILGenerator, ILGenerator> emitter; if (CanGenerateConverter(source, destination, out emitter)) { return(emitter(il)); } return(il.Castclass(destination)); }
/// <summary> /// 只读 /// </summary> private static void CloneActionRead(Type type, ILGenerator generator, PropertyInfo property) { var method = typeof(BuilderHelper).GetMethod(nameof(BuilderHelper.CloneObject), TConfig.Flags, null, new Type[] { typeof(object), typeof(object), typeof(bool) }, null); generator.GetValue(property, type); //获取引用值 generator.Emit(OpCodes.Ldarg_1); // los generator.Emit(OpCodes.Castclass, type); //未使用泛类,要转化为指定type类型 generator.Box(property); //值数据转引用数据 { //参数 generator.Emit(OpCodes.Ldc_I4, 1); } generator.Emit(OpCodes.Call, method);//调用静态方法 }
/// <summary> /// 只读 /// </summary> private static void CloneFuncRead(Type type, ILGenerator generator, PropertyInfo property) { var method = typeof(BuilderHelper).GetMethod(nameof(BuilderHelper.CloneObject), TConfig.Flags, null, new Type[] { typeof(object), typeof(object), typeof(bool) }, null); // Load initial object (parameter) (currently 2 items on eval stack) generator.GetValue(property, type);//获取引用值 // Load the new object on the eval stack... (currently 1 item on eval stack) generator.Emit(OpCodes.Ldloc_0); generator.Box(property); //值数据转引用数据 { //参数 generator.Emit(OpCodes.Ldc_I4, 1); } generator.Emit(OpCodes.Call, method);//调用静态方法 }
public override void ReadValueAfter(ILGenerator ilGen) { if (ReadValueMethod != null) { ilGen.Call(ReadValueMethod); if (BeforeType != AfterType) { if (AfterType.IsValueType) { ilGen.Box(AfterType); } ilGen.CastClass(BeforeType); if (BeforeType.IsValueType) { ilGen.UnboxAny(BeforeType); } } return; } var methodName = GetReadValueMethodName(BeforeType); if (methodName != null) { var method = typeof(IValueReader).GetMethod(methodName); if (methodName == nameof(IValueReader.ReadNullable) && method.IsGenericMethodDefinition) { method = method.MakeGenericMethod(Nullable.GetUnderlyingType(BeforeType)); } ilGen.Call(method); return; } var valueInterfaceType = typeof(ValueInterface <>).MakeGenericType(BeforeType); var valueInterfaceReadValueMethod = valueInterfaceType.GetMethod(nameof(ValueInterface <object> .ReadValue), StaticDeclaredOnly); ilGen.Call(valueInterfaceReadValueMethod); }
public override CodeNode VisitSkipAssignmentIfMissingValue(SkipAssignmentIfMissingValueNode node) { if (!_InFieldAssignment) { throw new InvalidOperationException("SkipAssignmentIfMissingValueNode must be in a FieldAssignmentNode"); } ILGen.Ldloca(_FieldLocal); ILGen.Ldc(node.MissingValue, node.MissingValue.GetType()); //BUG: Revisit this. The purpose of constrained is so you don't have to do different codegen for valuetype vs. reference type if (_FieldLocal.LocalType.IsValueType) { ILGen.Box(_FieldLocal.LocalType); } ILGen.Constrained(_FieldLocal.LocalType); // TODO: if (!node.AllowMissingValue) { do the next two lines... } ILGen.Callvirt(typeof(object).GetMethod("Equals", typeof(object))); ILGen.Brtrue(_SkipAssignmentLabel); return(node); }
public override void WriteValueAfter(ILGenerator ilGen) { if (WriteValueMethod != null) { if (BeforeType != AfterType) { if (BeforeType.IsValueType) { ilGen.Box(BeforeType); } ilGen.CastClass(AfterType); if (AfterType.IsValueType) { ilGen.UnboxAny(AfterType); } } ilGen.Call(WriteValueMethod); return; } var methodName = GetWriteValueMethodName(BeforeType); if (methodName != null) { ilGen.Call(typeof(IValueWriter).GetMethod(methodName)); return; } var valueInterfaceType = typeof(ValueInterface <>).MakeGenericType(BeforeType); var valueInterfaceWriteValueMethod = valueInterfaceType.GetMethod(nameof(ValueInterface <object> .WriteValue), StaticDeclaredOnly); ilGen.Call(valueInterfaceWriteValueMethod); }
public static ILGenerator Box <T>(this ILGenerator generator) where T : struct => generator.Box(typeof(T));
public static void Box <T>(this ILGenerator ilgen) { ilgen.Box(typeof(T)); }
public void EmitAppendToStringBuilder(ILGenerator gen, LocalBuilder?_, LocalBuilder?__, CsvColumnAttribute?attribute) => gen .Box <TEnum>() .Callvirt <StringBuilder>("Append", typeof(object));
/// <summary> /// 转化参数到类型,获取参数值,返回引用数据(指定类型时,调用转化) /// </summary> internal static void GetValue(this ILGenerator generator, PropertyInfo property, Type type) { generator.Emit(OpCodes.Ldarg_0); generator.Emit(OpCodes.Castclass, type); //未使用泛类,要转化为指定type类型 generator.Box(property); //值数据转引用数据 }
private void EmitStructConverter(ILGenerator il, Type inType, Type outType) { var casted = il.DeclareLocal(inType); var converted = il.DeclareLocal(outType); var v2 = il.DeclareLocal(objectType); var inPropMap = inType.GetProperties().ToDictionary(x => x.Name.ToLower()); var outCtor = outType.GetConstructors().OrderByDescending(x => x.GetParameters().Length).First(); var ctorParamMap = outCtor .GetParameters() .Select(outParam => { var outParamKey = outParam.Name.ToLower(); return(new { outParam, inProp = inPropMap.ContainsKey(outParamKey) ? inPropMap[outParamKey] : null }); }) .ToArray(); var invalidParamTransitions = ctorParamMap.Where(x => x.inProp == null).ToArray(); if (invalidParamTransitions.Length > 0) { throw new Exception($"Can't serialize this kind of struct. Need to know how to map next ctor params: {string.Join(", ", invalidParamTransitions.Select(x => x.outParam.Name))}"); } il.Ldarg(1); il.Unbox_Any(inType); il.Stloc(casted); il.Ldloca(converted); foreach (var ctorParamPair in ctorParamMap) { var inItem = ctorParamPair.inProp; var outItem = ctorParamPair.outParam; var inItemType = inItem.PropertyType; var outItemType = outItem.ParameterType; if (inItemType == outItemType) { il.Ldloca(casted); il.Call(inItem.GetMethod); } else { il.Ldsfld(ConverterStorage.InstanceFieldInfo); il.Ldtoken(inItemType); il.Call(typeOfMethodInfo); il.Ldtoken(outItemType); il.Call(typeOfMethodInfo); il.Callvirt(ConverterStorage.GetImplementationFieldInfo); il.Ldloca(casted); il.Call(inItem.GetMethod); il.Callvirt(convertMethodInfo); il.Castclass(outItemType); } } il.Call(outCtor); il.Ldloc(converted); il.Box(outType); il.Stloc(v2); var brLabel = il.DefineLabel(); il.BrS(brLabel); il.MarkLabel(brLabel); il.Ldloc(v2); il.Ret(); }