internal override void EmitGetter(CompilationContext context) { var getMethod = _property.GetGetMethod(true); context.LoadSource(LoadPurpose.MemberAccess); context.EmitCall(getMethod); context.CurrentType = MemberType; }
public static void EmitNullableExpression(this CompilationContext context, LocalBuilder local, Action <CompilationContext> nonNullExpression, Action <CompilationContext> nullExpression) { var label = context.DefineLabel(); if (local.LocalType.IsNullable()) { #if NetCore var variableType = local.LocalType.GetTypeInfo(); #else var variableType = local.LocalType; #endif context.Emit(OpCodes.Ldloca, local); context.EmitCall(variableType.GetProperty("HasValue").GetGetMethod()); context.Emit(OpCodes.Brfalse, label); context.Emit(OpCodes.Ldloca, local); context.EmitCall(variableType.GetProperty("Value").GetGetMethod()); context.CurrentType = variableType.GetGenericArguments()[0]; } else { context.Emit(OpCodes.Ldloc, local); context.Emit(OpCodes.Ldnull); context.EmitCall(_referenceEqualsMethod); context.Emit(OpCodes.Brtrue, label); context.Emit(OpCodes.Ldloc, local); context.CurrentType = local.LocalType; } nonNullExpression(context); var labelEnd = context.DefineLabel(); context.Emit(OpCodes.Br, labelEnd); context.MakeLabel(label); nullExpression(context); context.MakeLabel(labelEnd); }
public override void Emit(Type sourceType, Type targetType, CompilationContext context) { if (sourceType == typeof(string)) { return; } if (sourceType.IsNullable()) { var target = context.DeclareLocal(targetType); var local = context.DeclareLocal(sourceType); context.Emit(OpCodes.Stloc, local); context.EmitNullableExpression(local, ctx => { ctx.EmitCast(typeof(object)); ctx.EmitCall(_toStringMethod); ctx.Emit(OpCodes.Stloc, target); }, ctx => { ctx.EmitDefault(typeof(string)); ctx.Emit(OpCodes.Stloc, target); }); context.Emit(OpCodes.Ldloc, target); } #if NETSTANDARD else if (sourceType.GetTypeInfo().IsValueType) #else else if (sourceType.IsValueType) #endif { context.EmitCast(typeof(object)); context.EmitCall(_toStringMethod); } else { var target = context.DeclareLocal(targetType); var local = context.DeclareLocal(sourceType); context.Emit(OpCodes.Stloc, local); context.EmitNullableExpression(local, ctx => { ctx.EmitCast(typeof(object)); ctx.EmitCall(_toStringMethod); ctx.Emit(OpCodes.Stloc, target); }, ctx => { context.Emit(OpCodes.Ldnull); ctx.Emit(OpCodes.Stloc, target); }); context.Emit(OpCodes.Ldloc, target); } context.CurrentType = targetType; }
public void Emit(CompilationContext context) { if (_invokeMethod != null) { context.EmitCall(_invokeMethod); } else if (TypeMapper <TSource, TTarget> .TryGetInstance(_container, out var mapper)) { var sourceLocal = context.DeclareLocal(typeof(IEnumerable <TSource>)); context.EmitCast(typeof(IEnumerable <TSource>)); context.ILGenerator.Emit(OpCodes.Stloc, sourceLocal); EmitConverter(context.ILGenerator, mapper.ConverterMethod, () => context.ILGenerator.Emit(OpCodes.Ldloc, sourceLocal)); } context.CurrentType = typeof(IEnumerable <TTarget>); }
internal override void EmitSetter(CompilationContext context) { var local = context.DeclareLocal(context.CurrentType); context.Emit(OpCodes.Stloc, local); var setMethod = _property.GetSetMethod(true); context.LoadTarget(LoadPurpose.MemberAccess); context.Emit(OpCodes.Ldloc, local); if (MemberType != context.CurrentType) { context.EmitCast(MemberType); } context.EmitCall(setMethod); context.CurrentType = null; }
public void Emit(CompilationContext context) { context.EmitCall(_invokeMethod); context.CurrentType = typeof(TResult); }
public override void Emit(Type sourceType, Type targetType, CompilationContext context) { #if NetCore var reflectingTargetType = targetType.GetTypeInfo(); #else var reflectingTargetType = targetType; #endif var target = context.DeclareLocal(targetType); var local = context.DeclareLocal(sourceType); context.Emit(OpCodes.Stloc, local); if (targetType.IsNullable()) { var labelEnd = context.DefineLabel(); var labelFirst = context.DefineLabel(); // if(source == null) context.Emit(OpCodes.Ldloc, local); context.Emit(OpCodes.Brtrue, labelFirst); // target = null; context.Emit(OpCodes.Ldloca, target); context.Emit(OpCodes.Initobj, targetType); // goto end; context.Emit(OpCodes.Br, labelEnd); context.MakeLabel(labelFirst); // if(string.IsNullOrWhiteSpace(source)) var labelSecond = context.DefineLabel(); context.Emit(OpCodes.Ldloc, local); context.EmitCall(_checkEmptyMethod); context.Emit(OpCodes.Brfalse, labelSecond); // target = new Nullable<T>(default(T)); context.EmitDefault(reflectingTargetType.GetGenericArguments()[0]); context.Emit(OpCodes.Newobj, reflectingTargetType.GetConstructors()[0]); context.Emit(OpCodes.Stloc, target); // goto end; context.Emit(OpCodes.Br, labelEnd); context.MakeLabel(labelSecond); // target = new Nullable<$EnumType$>(($EnumType$)Enum.Parse(typeof($EnumType$),source)); // or // target = new Nullable<$TargetType$>($TargetType$.Parse(source)); var underlingType = reflectingTargetType.GetGenericArguments()[0]; #if NetCore if (underlingType.GetTypeInfo().IsEnum) #else if (underlingType.IsEnum) #endif { context.EmitTypeOf(underlingType); } context.Emit(OpCodes.Ldloc, local); context.EmitCall(_stringTrimMethod); context.EmitCall(GetConvertMethod(underlingType)); context.EmitCast(underlingType); context.Emit(OpCodes.Newobj, reflectingTargetType.GetConstructors()[0]); context.Emit(OpCodes.Stloc, target); context.MakeLabel(labelEnd); context.Emit(OpCodes.Ldloc, target); } else { // if(!string.IsNullOrWhiteSpace(source)) var label = context.DefineLabel(); context.Emit(OpCodes.Ldloc, local); context.EmitCall(_checkEmptyMethod); context.Emit(OpCodes.Brtrue, label); // target = ($EnumType$)Enum.Parse(typeof($EnumType$),source); // or // target = $TargetType$.Parse(source); if (reflectingTargetType.IsEnum) { context.EmitTypeOf(targetType); } context.Emit(OpCodes.Ldloc, local); context.EmitCall(_stringTrimMethod); context.EmitCall(GetConvertMethod(targetType)); context.EmitCast(targetType); context.Emit(OpCodes.Stloc, target); // goto end; var labelEnd = context.DefineLabel(); context.Emit(OpCodes.Br, labelEnd); // target = default(T); context.MakeLabel(label); context.EmitDefault(targetType); context.Emit(OpCodes.Stloc, target); context.MakeLabel(labelEnd); context.Emit(OpCodes.Ldloc, target); } }
public void Emit(CompilationContext context) { context.EmitCall(_invokeMethod); context.CurrentType = typeof(IEnumerable <TTarget>); }
public static void EmitDefault(this CompilationContext context, Type targetType) { var originalType = targetType; if (targetType.IsNullable()) { var local = context.DeclareLocal(targetType); context.Emit(OpCodes.Ldloca, local); context.Emit(OpCodes.Initobj, targetType); context.Emit(OpCodes.Ldloc, local); context.CurrentType = originalType; return; } #if NetCore if (!targetType.GetTypeInfo().IsValueType) #else if (!targetType.IsValueType) #endif { context.Emit(OpCodes.Ldnull); context.CurrentType = originalType; return; } #if NetCore if (targetType.GetTypeInfo().IsEnum) #else if (targetType.IsEnum) #endif { targetType = Enum.GetUnderlyingType(targetType); } if (targetType == typeof(int) || targetType == typeof(uint) || targetType == typeof(short) || targetType == typeof(ushort) || targetType == typeof(byte) || targetType == typeof(sbyte) || targetType == typeof(char) || targetType == typeof(bool)) { context.Emit(OpCodes.Ldc_I4_0); context.CurrentType = originalType; return; } if (targetType == typeof(long) || targetType == typeof(ulong)) { context.Emit(OpCodes.Ldc_I4_0); context.Emit(OpCodes.Conv_I8); context.CurrentType = originalType; return; } if (targetType == typeof(float)) { context.Emit(OpCodes.Ldc_I4_0); context.Emit(OpCodes.Conv_R4); context.CurrentType = originalType; return; } if (targetType == typeof(double)) { context.Emit(OpCodes.Ldc_I4_0); context.Emit(OpCodes.Conv_R8); context.CurrentType = originalType; return; } Func <MethodInfo, bool> coverterPredicate = method => { if (method.Name == "op_Implicit") { var parameters = method.GetParameters(); return(parameters.Length == 1 && parameters[0].ParameterType == typeof(int)); } return(false); }; #if NetCore var reflectingType = targetType.GetTypeInfo(); if (targetType == typeof(decimal)) { context.Emit(OpCodes.Ldc_I4_0); context.EmitCall(reflectingType.GetMethods(BindingFlags.Static | BindingFlags.Public).FirstOrDefault(coverterPredicate)); context.CurrentType = originalType; return; } #else var reflectingType = targetType; if (targetType == typeof(decimal)) { context.Emit(OpCodes.Ldc_I4_0); context.EmitCall(reflectingType.GetMethods(BindingFlags.Static | BindingFlags.Public).FirstOrDefault(coverterPredicate)); context.CurrentType = originalType; return; } #endif var field = reflectingType.GetField("Empty", BindingFlags.Public | BindingFlags.Static) ?? reflectingType.GetField("Zero", BindingFlags.Public | BindingFlags.Static) ?? reflectingType.GetField("MinValue", BindingFlags.Public | BindingFlags.Static); if (field != null) { context.Emit(OpCodes.Ldsfld, field); context.CurrentType = field.FieldType; context.EmitCast(originalType); return; } var property = reflectingType.GetProperty("Empty", BindingFlags.Public | BindingFlags.Static) ?? reflectingType.GetProperty("Zero", BindingFlags.Public | BindingFlags.Static) ?? reflectingType.GetProperty("MinValue", BindingFlags.Public | BindingFlags.Static); var getMethod = property?.GetGetMethod(); if (getMethod != null) { context.EmitCall(getMethod); context.CurrentType = getMethod.ReturnType; context.EmitCast(originalType); return; } var targetLocal = context.DeclareLocal(targetType); context.Emit(OpCodes.Ldloca, targetLocal); context.Emit(OpCodes.Initobj, targetType); context.Emit(OpCodes.Ldloc, targetLocal); context.CurrentType = originalType; }
public void Emit(CompilationContext context) { context.EmitCall(_invokeMethod); context.CurrentType = null; }
public override void Emit(Type sourceType, Type targetType, CompilationContext context) { #if NETSTANDARD var reflectingTargetType = targetType.GetTypeInfo(); #else var reflectingTargetType = targetType; #endif context.EmitCast(typeof(IEnumerable <>).MakeGenericType(_sourceElementType)); _invokerBuilder.Emit(context); if (reflectingTargetType.IsGenericType) { var genericTypeDefinition = targetType.GetGenericTypeDefinition(); if (genericTypeDefinition == typeof(IList <>) || genericTypeDefinition == typeof(ICollection <>) || genericTypeDefinition == typeof(IEnumerable <>)) { context.EmitCast(targetType); context.CurrentType = targetType; return; } } else if (targetType.IsArray) { context.EmitCast(targetType); context.CurrentType = targetType; return; } var labelNull = context.DefineLabel(); var labelComplete = context.DefineLabel(); var local = context.DeclareLocal(context.CurrentType); context.Emit(OpCodes.Stloc, local); context.Emit(OpCodes.Ldloc, local); context.Emit(OpCodes.Brfalse, labelNull); context.Emit(OpCodes.Ldloc, local); if (targetType.IsEnumerable(out var targetElementType)) { var constructor = reflectingTargetType.GetConstructor(new[] { typeof(IEnumerable <>).MakeGenericType(targetElementType) }) ?? reflectingTargetType.GetConstructor(new[] { typeof(IList <>).MakeGenericType(targetElementType) }) ?? reflectingTargetType.GetConstructor(new[] { typeof(ICollection <>).MakeGenericType(targetElementType) }) ?? reflectingTargetType.GetConstructor(new[] { targetElementType.MakeArrayType() }); if (constructor != null) { context.EmitCast(constructor.GetParameters()[0].ParameterType); context.Emit(OpCodes.Newobj, constructor); } else { var defaultConstructor = reflectingTargetType.GetConstructor(Type.EmptyTypes); var addMethod = reflectingTargetType.GetMethods(BindingFlags.Instance | BindingFlags.Public).Where(method => { if (method.Name != "Add") { return(false); } var parameters = method.GetParameters(); return(parameters.Length == 1 && parameters[0].ParameterType == targetElementType); }).FirstOrDefault(); if (defaultConstructor != null && addMethod != null) { var targetArrayType = targetElementType.MakeArrayType(); var targetArray = context.DeclareLocal(targetArrayType); var targetInstance = context.DeclareLocal(targetType); var index = context.DeclareLocal(typeof(int)); context.EmitCast(targetArrayType); context.Emit(OpCodes.Stloc, targetArray); context.Emit(OpCodes.Newobj, defaultConstructor); context.Emit(OpCodes.Stloc, targetInstance); // var i = 0; context.Emit(OpCodes.Ldc_I4_0); context.Emit(OpCodes.Stloc, index); var labelEnd = context.DefineLabel(); context.Emit(OpCodes.Br_S, labelEnd); var labelStart = context.DefineLabel(); context.MakeLabel(labelStart); // target.Add(array[i]); context.Emit(OpCodes.Ldloc, targetInstance); context.Emit(OpCodes.Ldloc, targetArray); context.Emit(OpCodes.Ldloc, index); #if NETSTANDARD var targetElementTypeInfo = targetElementType.GetTypeInfo(); if (targetElementTypeInfo.IsValueType && !targetElementTypeInfo.IsPrimitive) #else if (targetElementType.IsValueType && !targetElementType.IsPrimitive) #endif { context.Emit(OpCodes.Ldelema, targetElementType); } else { context.Emit(OpCodes.Ldelem, targetElementType); } context.EmitCall(addMethod); // i++ context.Emit(OpCodes.Ldloc, index); context.Emit(OpCodes.Ldc_I4_1); context.Emit(OpCodes.Add); context.Emit(OpCodes.Stloc, index); context.MakeLabel(labelEnd); context.Emit(OpCodes.Ldloc, index); context.Emit(OpCodes.Ldloc, targetArray); context.Emit(OpCodes.Ldlen); context.Emit(OpCodes.Conv_I4); context.Emit(OpCodes.Blt_S, labelStart); context.Emit(OpCodes.Ldloc, targetInstance); } } } context.Emit(OpCodes.Br_S, labelComplete); context.MakeLabel(labelNull); context.Emit(OpCodes.Ldnull); context.MakeLabel(labelComplete); context.CurrentType = targetType; }