private bool EmitNullableSource(CompilationContext context, Type sourceType, Type targetType) { #if NETSTANDARD var reflectingSourceType = sourceType.GetTypeInfo(); #else var reflectingSourceType = sourceType; #endif var sourceUnderlingType = reflectingSourceType.GetGenericArguments()[0]; var converter = GetConvertEmitter(sourceUnderlingType, targetType); if (converter != null) { var target = context.DeclareLocal(targetType); var local = context.DeclareLocal(sourceType); context.Emit(OpCodes.Stloc, local); context.EmitNullableExpression(local, ctx => { converter(ctx); ctx.Emit(OpCodes.Stloc, target); }, ctx => { context.EmitDefault(targetType); context.Emit(OpCodes.Stloc, target); }); context.Emit(OpCodes.Ldloc, target); return(true); } return(false); }
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); } }