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; }
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); }
private bool EmitBothNullable(CompilationContext context, Type sourceType, Type targetType) { #if NETSTANDARD var reflectingTargetType = targetType.GetTypeInfo(); var reflectingSourceType = sourceType.GetTypeInfo(); #else var reflectingTargetType = targetType; var reflectingSourceType = sourceType; #endif var sourceUnderlingType = reflectingSourceType.GetGenericArguments()[0]; var targetUnderlingyType = reflectingTargetType.GetGenericArguments()[0]; // When the source and target member are the same nullbale type if (targetUnderlingyType == sourceUnderlingType) { return(true); } // When the source and target member are not the same nullable type, // But their underlying type can be implicitly or explicitly converted. var converter = GetConvertEmitter(sourceUnderlingType, targetUnderlingyType); 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.Newobj, reflectingTargetType.GetConstructors()[0]); ctx.Emit(OpCodes.Stloc, target); }, ctx => { ctx.EmitDefault(targetType); ctx.Emit(OpCodes.Stloc, target); }); context.Emit(OpCodes.Ldloc, target); return(true); } return(false); }