コード例 #1
0
        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;
        }
コード例 #2
0
        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);
        }
コード例 #3
0
        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);
        }