Пример #1
0
 public void EmitConvert(Type from, Type to, bool check = false)
 {
     if (from == to)
     {
         return;
     }
     if (!from.IsValueType)
     {
         if (!to.IsValueType)
         {
             Il.Castclass(to);
         }
         else
         {
             if (from != typeof(object) && !(from == typeof(Enum) && to.IsEnum))
             {
                 throw new InvalidCastException("Cannot cast an object of type '" + from + "' to type '" + to + "'");
             }
             Il.Unbox_Any(to);
         }
     }
     else
     {
         if (!to.IsValueType)
         {
             if (to != typeof(object) && !(to == typeof(Enum) && from.IsEnum))
             {
                 throw new InvalidCastException("Cannot cast an object of type '" + from + "' to type '" + to + "'");
             }
             Il.Box(from);
         }
         else
         {
             if (to.IsNullable())
             {
                 var toArgument = to.GetGenericArguments()[0];
                 if (from.IsNullable())
                 {
                     var fromArgument = from.GetGenericArguments()[0];
                     using (var temp = DeclareLocal(from))
                     {
                         Il.Stloc(temp);
                         Il.Ldloca(temp);
                         EmitHasValueAccess(from);
                         var valueIsNullLabel = Il.DefineLabel("valueIsNull");
                         Il.Brfalse(valueIsNullLabel);
                         Il.Ldloca(temp);
                         EmitValueAccess(from);
                         if (toArgument != fromArgument)
                         {
                             EmitConvert(fromArgument, toArgument, check);
                         }
                         Il.Newobj(to.GetConstructor(new[] { toArgument }));
                         var doneLabel = Il.DefineLabel("done");
                         Il.Br(doneLabel);
                         MarkLabelAndSurroundWithSP(valueIsNullLabel);
                         EmitLoadDefaultValue(to);
                         MarkLabelAndSurroundWithSP(doneLabel);
                     }
                 }
                 else
                 {
                     if (toArgument != from)
                     {
                         EmitConvert(from, toArgument, check);
                     }
                     Il.Newobj(to.GetConstructor(new[] { toArgument }));
                 }
             }
             else if (from.IsNullable())
             {
                 var fromArgument = from.GetGenericArguments()[0];
                 using (var temp = DeclareLocal(from))
                 {
                     Il.Stloc(temp);
                     Il.Ldloca(temp);
                     var valueIsNullLabel = Il.DefineLabel("valueIsNull");
                     Il.Brfalse(valueIsNullLabel);
                     Il.Ldloca(temp);
                     EmitValueAccess(from);
                     if (to != fromArgument)
                     {
                         EmitConvert(fromArgument, to, check);
                     }
                     var doneLabel = Il.DefineLabel("done");
                     Il.Br(doneLabel);
                     MarkLabelAndSurroundWithSP(valueIsNullLabel);
                     EmitLoadDefaultValue(to);
                     MarkLabelAndSurroundWithSP(doneLabel);
                 }
             }
             else if (to.IsEnum || to == typeof(Enum))
             {
                 EmitConvert(from, typeof(int), check);
             }
             else if (from.IsEnum || from == typeof(Enum))
             {
                 EmitConvert(typeof(int), to, check);
             }
             else
             {
                 if (!check)
                 {
                     EmitConvertValue(Il, from, to);
                 }
                 else
                 {
                     EmitConvertValueChecked(Il, from, to);
                 }
             }
         }
     }
 }