예제 #1
0
        // TODO: revisit
        /// <summary>
        /// Converts the provided expression to the given type.  The expression is safe to evaluate multiple times.
        /// </summary>
        public virtual Expression ConvertExpression(Expression expr, Type toType, ConversionResultKind kind, OverloadResolverFactory resolverFactory)
        {
            ContractUtils.RequiresNotNull(expr, "expr");
            ContractUtils.RequiresNotNull(toType, "toType");

            Type exprType = expr.Type;

            if (toType == typeof(object))
            {
                if (exprType.IsValueType())
                {
                    return(AstUtils.Convert(expr, toType));
                }
                else
                {
                    return(expr);
                }
            }

            if (toType.IsAssignableFrom(exprType))
            {
                return(expr);
            }

            return(Expression.Convert(expr, CompilerHelpers.GetVisibleType(toType)));
        }
예제 #2
0
        public StandardRule <T> MakeRule()
        {
            Type toType    = Action.ToType;
            Type knownType = CompilerHelpers.GetVisibleType(_rule.Parameters[0].Type);

            // check for conversion to object first...
            if (TryConvertToObject(toType, knownType))
            {
                _rule.AddTest(Ast.Constant(true));
                return(_rule);
            }

            // do checks that aren't based upon strongly knowing the object's type (and don't require tests)
            if (TryAllConversions(toType, knownType))
            {
                _rule.AddTest(Ast.Constant(true));
                return(_rule);
            }

            // try again w/ a test for the known-type
            Type type = CompilerHelpers.GetType(_arg);

            _rule.AddTest(_rule.MakeTypeTest(type, 0));

            if (TryAllConversions(toType, type))
            {
                return(_rule);
            }

            // no conversion is available, make an error rule.
            MakeErrorTarget();
            return(_rule);
        }
예제 #3
0
        public override Ast ConvertExpression(Ast expr, Type toType, ConversionResultKind kind, OverloadResolverFactory resolverFactory)
        {
            Type exprType = expr.Type;
            Type visType  = CompilerHelpers.GetVisibleType(toType);

            if (typeof(IFn).IsAssignableFrom(exprType) && typeof(Delegate).IsAssignableFrom(visType))
            {
                return(Ast.Call(typeof(Converter).GetMethod("ConvertToDelegate"), Ast.Convert(expr, typeof(IFn)), Expression.Constant(visType)));
            }

            // Follow through on our promise to convert IEnumerable<Object> or IEnumerable to IEnumerable<T> for any T
            if (toType.IsGenericType && !toType.IsAssignableFrom(expr.Type))
            {
                // The following is inspired by IronPython.Runtime.Binding.Python.ConversionBinder.FallbackConvert
                Type genTo = toType.GetGenericTypeDefinition();
                if (genTo == typeof(IList <>))
                {
                    return(MakeToGenericConversion(expr, toType, typeof(IList <object>), typeof(ListGenericWrapper <>)));
                }
                else if (genTo == typeof(IDictionary <,>))
                {
                    return(MakeToGenericConversion(expr, toType, typeof(IDictionary <object, object>), typeof(DictionaryGenericWrapper <,>)));
                }
                else if (genTo == typeof(IEnumerable <>))
                {
                    return(MakeToGenericConversion(expr, toType, typeof(IEnumerable), typeof(IEnumerableOfTWrapper <>)));
                }
            }

            return(base.ConvertExpression(expr, toType, kind, resolverFactory));
        }
예제 #4
0
 /// <summary>
 /// Helper to produce a rule when no conversion is required (the strong type of the expression
 /// input matches the type we're converting to or has an implicit conversion at the IL level)
 /// </summary>
 private void MakeSimpleConversionTarget(Type toType, Type knownType)
 {
     if (toType.IsValueType && _rule.ReturnType == typeof(object) && _rule.Parameters[0].Type == typeof(object))
     {
         // boxed value type is being converted back to object.  We've done
         // the type check, there's no need to unbox & rebox the value.  infact
         // it breaks calls on instance methods so we need to avoid it.
         _rule.Target =
             _rule.MakeReturn(
                 Binder,
                 _rule.Parameters[0]
                 );
     }
     else
     {
         Expression arg = _rule.Parameters[0];
         if (arg.Type != knownType && knownType != typeof(Null))
         {
             arg = Ast.Convert(arg, CompilerHelpers.GetVisibleType(knownType));
         }
         _rule.Target =
             _rule.MakeReturn(
                 Binder,
                 AstUtils.Convert(arg, CompilerHelpers.GetVisibleType(toType))
                 );
     }
 }
예제 #5
0
        public static MetaObject Restrict(this MetaObject self, Type type)
        {
            ContractUtils.RequiresNotNull(self, "self");
            ContractUtils.RequiresNotNull(type, "type");

            IRestrictedMetaObject rmo = self as IRestrictedMetaObject;

            if (rmo != null)
            {
                return(rmo.Restrict(type));
            }

            if (type == self.Expression.Type)
            {
                if (type.IsSealedOrValueType())
                {
                    return(self);
                }

                if (self.Expression.NodeType == ExpressionType.New ||
                    self.Expression.NodeType == ExpressionType.NewArrayBounds ||
                    self.Expression.NodeType == ExpressionType.NewArrayInit)
                {
                    return(self);
                }
            }

            if (type == typeof(Null))
            {
                return(new MetaObject(
                           Expression.Constant(null),
                           self.Restrictions.Merge(Restrictions.GetInstanceRestriction(self.Expression, null)),
                           self.Value
                           ));
            }

            if (self.HasValue)
            {
                return(new MetaObject(
                           AstUtils.Convert(
                               self.Expression,
                               CompilerHelpers.GetVisibleType(type)
                               ),
                           self.Restrictions.Merge(Restrictions.GetTypeRestriction(self.Expression, type)),
                           self.Value
                           ));
            }

            return(new MetaObject(
                       AstUtils.Convert(
                           self.Expression,
                           CompilerHelpers.GetVisibleType(type)
                           ),
                       self.Restrictions.Merge(Restrictions.GetTypeRestriction(self.Expression, type))
                       ));
        }
예제 #6
0
        public override Ast ConvertExpression(Ast expr, Type toType, ConversionResultKind kind, OverloadResolverFactory resolverFactory)
        {
            Type exprType = expr.Type;
            Type visType  = CompilerHelpers.GetVisibleType(toType);

            if (typeof(IFn).IsAssignableFrom(exprType) && typeof(Delegate).IsAssignableFrom(visType))
            {
                return(Ast.Call(typeof(Converter).GetMethod("ConvertToDelegate"), Ast.Convert(expr, typeof(IFn)), Expression.Constant(visType)));
            }

            return(base.ConvertExpression(expr, toType, kind, resolverFactory));
        }
        public static DynamicMetaObject Restrict(this DynamicMetaObject self, Type type)
        {
            ContractUtils.RequiresNotNull(self, "self");
            ContractUtils.RequiresNotNull(type, "type");

            IRestrictedMetaObject rmo = self as IRestrictedMetaObject;

            if (rmo != null)
            {
                return(rmo.Restrict(type));
            }

            if (type == self.Expression.Type)
            {
                if (type.IsSealed ||
                    self.Expression.NodeType == ExpressionType.New ||
                    self.Expression.NodeType == ExpressionType.NewArrayBounds ||
                    self.Expression.NodeType == ExpressionType.NewArrayInit)
                {
                    return(self.Clone(self.Restrictions.Merge(BindingRestrictionsHelpers.GetRuntimeTypeRestriction(self.Expression, type))));
                }
            }

            if (type == typeof(DynamicNull))
            {
                return(self.Clone(
                           AstUtils.Constant(null),
                           self.Restrictions.Merge(BindingRestrictions.GetInstanceRestriction(self.Expression, null))
                           ));
            }

            Expression converted;

            // if we're converting to a value type just unbox to preserve
            // object identity.  If we're converting from Enum then we're
            // going to a specific enum value and an unbox is not allowed.
            if (type.IsValueType && self.Expression.Type != typeof(Enum))
            {
                converted = Expression.Unbox(
                    self.Expression,
                    CompilerHelpers.GetVisibleType(type)
                    );
            }
            else
            {
                converted = AstUtils.Convert(
                    self.Expression,
                    CompilerHelpers.GetVisibleType(type)
                    );
            }

            return(self.Clone(converted, self.Restrictions.Merge(BindingRestrictionsHelpers.GetRuntimeTypeRestriction(self.Expression, type))));
        }
예제 #8
0
        internal virtual void BuildInvoke(MetaObjectBuilder /*!*/ metaBuilder, CallArguments /*!*/ args)
        {
            Assert.NotNull(metaBuilder, args);
            Debug.Assert(args.Target == this);

            // first argument must be this method:
            metaBuilder.AddRestriction(Ast.Equal(args.TargetExpression, AstUtils.Constant(this)));

            // set the target (becomes self in the called method):
            args.SetTarget(AstUtils.Constant(_target, CompilerHelpers.GetVisibleType(_target)), _target);

            _info.BuildCall(metaBuilder, args, _name);
        }
예제 #9
0
        private MethodBase[] GetBoundMemberTargets(BoundMemberTracker bmt)
        {
            Debug.Assert(bmt.Instance == null); // should be null for trackers that leak to user code

            MethodBase[] targets;
            _instance = Ast.Convert(
                Ast.ReadProperty(
                    Ast.Convert(Rule.Parameters[0], typeof(BoundMemberTracker)),
                    typeof(BoundMemberTracker).GetProperty("ObjectInstance")
                    ),
                CompilerHelpers.GetVisibleType(CompilerHelpers.GetType(bmt.ObjectInstance))
                );
            _test = Ast.AndAlso(
                _test,
                Ast.Equal(
                    Ast.ReadProperty(
                        Ast.Convert(Rule.Parameters[0], typeof(BoundMemberTracker)),
                        typeof(BoundMemberTracker).GetProperty("BoundTo")
                        ),
                    Ast.RuntimeConstant(bmt.BoundTo)
                    )
                );
            _test = Ast.AndAlso(
                _test,
                Rule.MakeTypeTest(
                    CompilerHelpers.GetType(bmt.ObjectInstance),
                    Ast.ReadProperty(
                        Ast.Convert(Rule.Parameters[0], typeof(BoundMemberTracker)),
                        typeof(BoundMemberTracker).GetProperty("ObjectInstance")
                        )
                    )
                );
            switch (bmt.BoundTo.MemberType)
            {
            case TrackerTypes.MethodGroup:
                targets = ((MethodGroup)bmt.BoundTo).GetMethodBases();
                break;

            case TrackerTypes.Method:
                targets = new MethodBase[] { ((MethodTracker)bmt.BoundTo).Method };
                break;

            default:
                throw new InvalidOperationException();     // nothing else binds yet
            }
            return(targets);
        }
예제 #10
0
 private static void AddArgument(List <Expression> /*!*/ actualArgs, object arg, Expression /*!*/ expr)
 {
     if (arg == null)
     {
         actualArgs.Add(Ast.Constant(null));
     }
     else
     {
         var type = CompilerHelpers.GetVisibleType(arg);
         if (type.IsValueType)
         {
             actualArgs.Add(expr);
         }
         else
         {
             actualArgs.Add(AstUtils.Convert(expr, type));
         }
     }
 }
        /// <summary>
        /// Helper to produce a rule when no conversion is required (the strong type of the expression
        /// input matches the type we're converting to or has an implicit conversion at the IL level)
        /// </summary>
        private static DynamicMetaObject MakeSimpleConversionTarget(Type toType, BindingRestrictions restrictions, DynamicMetaObject arg)
        {
            return(new DynamicMetaObject(
                       AstUtils.Convert(arg.Expression, CompilerHelpers.GetVisibleType(toType)),
                       restrictions));

            /*
             * if (toType.IsValueType && _rule.ReturnType == typeof(object) && Expression.Type == typeof(object)) {
             *  // boxed value type is being converted back to object.  We've done
             *  // the type check, there's no need to unbox & rebox the value.  infact
             *  // it breaks calls on instance methods so we need to avoid it.
             *  _rule.Target =
             *      _rule.MakeReturn(
             *          Binder,
             *          Expression
             *      );
             * }
             * */
        }
예제 #12
0
        /// <summary>
        /// Converts the provided expression to the given type.  The expression is safe to evaluate multiple times.
        /// </summary>
        public virtual Expression ConvertExpression(Expression expr, Type toType, ConversionResultKind kind, Expression context)
        {
            ContractUtils.RequiresNotNull(expr, "expr");
            ContractUtils.RequiresNotNull(toType, "toType");

            Type exprType = expr.Type;

            if (toType == typeof(object))
            {
                if (exprType.IsValueType)
                {
                    return(Expression.Convert(expr, toType));
                }
                else
                {
                    return(expr);
                }
            }

            if (toType.IsAssignableFrom(exprType))
            {
                return(expr);
            }

            Type visType = CompilerHelpers.GetVisibleType(toType);

            Expression[] args;
            if (context != null)
            {
                args = new Expression[] { context, expr };
            }
            else
            {
                args = new Expression[] { expr };
            }

            return(Expression.Dynamic(
                       OldConvertToAction.Make(this, visType, kind),
                       visType,
                       args
                       ));
        }
예제 #13
0
        /// <summary>
        /// Creates a call to this MethodTarget with the specified parameters.  Casts are inserted to force
        /// the types to the provided known types.
        ///
        /// TODO: Remove RuleBuilder and knownTypes once we're fully meta
        /// </summary>
        /// <param name="parameterBinder">ParameterBinder used to map arguments to parameters.</param>
        /// <param name="parameters">The explicit arguments</param>
        /// <param name="knownTypes">If non-null, the type for each element in parameters</param>
        /// <returns></returns>
        internal Expression MakeExpression(ParameterBinder parameterBinder, IList <Expression> parameters, IList <Type> knownTypes)
        {
            Debug.Assert(knownTypes == null || parameters.Count == knownTypes.Count);

            IList <Expression> args = parameters;

            if (knownTypes != null)
            {
                args = new Expression[parameters.Count];
                for (int i = 0; i < args.Count; i++)
                {
                    args[i] = parameters[i];
                    if (knownTypes[i] != null && !knownTypes[i].IsAssignableFrom(parameters[i].Type))
                    {
                        args[i] = Ast.Convert(parameters[i], CompilerHelpers.GetVisibleType(knownTypes[i]));
                    }
                }
            }

            return(MakeExpression(parameterBinder, args));
        }
예제 #14
0
        public void MakeRule()
        {
            Type toType    = Action.ToType;
            Type knownType = CompilerHelpers.GetVisibleType(_rule.Parameters[0].Type);

            // check for conversion to object first...
            if (TryConvertToObject(toType, knownType))
            {
                _rule.AddTest(Ast.Constant(true));
                return;
            }

            // do checks that aren't based upon strongly knowing the object's type (and don't require tests)
            if (TryAllConversions(toType, knownType))
            {
                _rule.AddTest(Ast.Constant(true));
                return;
            }

            // try again w/ a test for the known-type
            Type type = CompilerHelpers.GetType(_arg);

            _rule.AddTest(_rule.MakeTypeTest(type, 0));

            if (TryAllConversions(toType, type))
            {
                return;
            }

            // finally try conversions that aren't based upon the incoming type at all but
            // are last chance conversions based on the destination type
            if (TryExtraConversions(toType))
            {
                return;
            }

            // no conversion is available, make an error rule.
            MakeErrorTarget();
        }
예제 #15
0
        private DynamicMetaObject /*!*/ GetInstance(Expression /*!*/ instance, Type /*!*/ testType)
        {
            Assert.NotNull(instance, testType);
            object instanceValue = Value.BindingSelf;

            BindingRestrictions restrictions = BindingRestrictionsHelpers.GetRuntimeTypeRestriction(instance, testType);

            // cast the instance to the correct type
            if (CompilerHelpers.IsStrongBox(instanceValue))
            {
                instance      = ReadStrongBoxValue(instance);
                instanceValue = ((IStrongBox)instanceValue).Value;
            }
            else if (!testType.IsEnum)
            {
                // We need to deal w/ wierd types like MarshalByRefObject.
                // We could have an MBRO whos DeclaringType is completely different.
                // Therefore we special case it here and cast to the declaring type

                Type selfType = CompilerHelpers.GetType(Value.BindingSelf);
                selfType = CompilerHelpers.GetVisibleType(selfType);

                if (selfType == typeof(object) && Value.DeclaringType.IsInterface)
                {
                    selfType = Value.DeclaringType;
                }

                if (Value.DeclaringType.IsInterface && selfType.IsValueType)
                {
                    // explicit interface implementation dispatch on a value type, don't
                    // unbox the value type before the dispatch.
                    instance = AstUtils.Convert(instance, Value.DeclaringType);
                }
                else if (selfType.IsValueType)
                {
                    // We might be calling a a mutating method (like
                    // Rectangle.Intersect). If so, we want it to mutate
                    // the boxed value directly
                    instance = Ast.Unbox(instance, selfType);
                }
                else
                {
#if SILVERLIGHT
                    instance = AstUtils.Convert(instance, selfType);
#else
                    Type convType = selfType == typeof(MarshalByRefObject) ? CompilerHelpers.GetVisibleType(Value.DeclaringType) : selfType;

                    instance = AstUtils.Convert(instance, convType);
#endif
                }
            }
            else
            {
                // we don't want to cast the enum to its real type, it will unbox it
                // and turn it into its underlying type.  We presumably want to call
                // a method on the Enum class though - so we cast to Enum instead.
                instance = AstUtils.Convert(instance, typeof(Enum));
            }
            return(new DynamicMetaObject(
                       instance,
                       restrictions,
                       instanceValue
                       ));
        }
        public override Expression /*!*/ Convert(DynamicMetaObject /*!*/ metaObject, Type restrictedType, ParameterInfo info, Type /*!*/ toType)
        {
            Expression expr     = metaObject.Expression;
            Type       fromType = restrictedType ?? expr.Type;

            // block:
            if (fromType == typeof(MissingBlockParam))
            {
                Debug.Assert(toType == typeof(BlockParam) || toType == typeof(MissingBlockParam));
                return(AstUtils.Constant(null));
            }

            if (fromType == typeof(BlockParam) && toType == typeof(MissingBlockParam))
            {
                return(AstUtils.Constant(null));
            }

            // protocol conversions:
            if (info != null && info.IsDefined(typeof(DefaultProtocolAttribute), false))
            {
                var action = RubyConversionAction.TryGetDefaultConversionAction(Context, toType);
                if (action != null)
                {
                    // TODO: inline implicit conversions:
                    return(AstUtils.LightDynamic(action, toType, expr));
                }

                // Do not throw an exception here to allow generic type parameters to be used with D.P. attribute.
                // The semantics should be to use DP if available for the current instantiation and ignore it otherwise.
            }

            if (restrictedType != null)
            {
                if (restrictedType == typeof(DynamicNull))
                {
                    if (!toType.IsValueType || toType.IsGenericType && toType.GetGenericTypeDefinition() == typeof(Nullable <>))
                    {
                        return(AstUtils.Constant(null, toType));
                    }
                    else if (toType == typeof(bool))
                    {
                        return(AstUtils.Constant(false));
                    }
                }

                if (toType.IsAssignableFrom(restrictedType))
                {
                    // expr can be converted to restrictedType, which can be converted toType => we can convert expr to toType:
                    return(AstUtils.Convert(expr, CompilerHelpers.GetVisibleType(toType)));
                }

                // if there is a simple conversion from restricted type, convert the expression to the restricted type and use that conversion:
                Type visibleRestrictedType = CompilerHelpers.GetVisibleType(restrictedType);
                if (Converter.CanConvertFrom(metaObject, visibleRestrictedType, toType, false, NarrowingLevel.None, false, false).IsConvertible)
                {
                    expr = AstUtils.Convert(expr, visibleRestrictedType);
                }
            }

            return(Converter.ConvertExpression(expr, toType, _args.RubyContext, _args.MetaContext.Expression, _implicitProtocolConversions));
        }
예제 #17
0
 /// <summary>
 ///   Helper to produce a rule when no conversion is required (the strong type of the expression
 ///   input matches the type we're converting to or has an implicit conversion at the IL level)
 /// </summary>
 private static MSAst MakeSimpleConversionTarget(Type toType, MSAst arg)
 {
     return(AstUtils.Convert(arg, CompilerHelpers.GetVisibleType(toType)));
 }
예제 #18
0
        public override Expression ConvertExpression(Expression /*!*/ expr, Type /*!*/ toType, ConversionResultKind kind, Expression context)
        {
            Type fromType = expr.Type;

            if (toType == typeof(object))
            {
                if (fromType.IsValueType)
                {
                    return(Ast.Convert(expr, toType));
                }
                else
                {
                    return(expr);
                }
            }

            if (toType.IsAssignableFrom(fromType))
            {
                return(expr);
            }

            // We used to have a special case for int -> double...
            if (fromType != typeof(object) && fromType.IsValueType)
            {
                expr = Ast.Convert(expr, typeof(object));
            }

            MethodInfo fastConvertMethod = GetFastConvertMethod(toType);

            if (fastConvertMethod != null)
            {
                return(Ast.Call(fastConvertMethod, AstUtils.Convert(expr, typeof(object))));
            }

            if (typeof(Delegate).IsAssignableFrom(toType))
            {
                return(Ast.Convert(
                           Ast.Call(
                               typeof(Converter).GetMethod("ConvertToDelegate"),
                               AstUtils.Convert(expr, typeof(object)),
                               Ast.Constant(toType)
                               ),
                           toType
                           ));
            }

            Expression typeIs;
            Type       visType = CompilerHelpers.GetVisibleType(toType);

            if (toType.IsVisible)
            {
                typeIs = Ast.TypeIs(expr, toType);
            }
            else
            {
                typeIs = Ast.Call(
                    AstUtils.Convert(Ast.Constant(toType), typeof(Type)),
                    typeof(Type).GetMethod("IsInstanceOfType"),
                    AstUtils.Convert(expr, typeof(object))
                    );
            }

            return(Ast.Condition(
                       typeIs,
                       Ast.Convert(
                           expr,
                           visType),
                       Ast.Convert(
                           Ast.Call(
                               GetGenericConvertMethod(visType),
                               AstUtils.Convert(expr, typeof(object)),
                               Ast.Constant(visType.TypeHandle)
                               ),
                           visType
                           )
                       ));
        }
예제 #19
0
        private DynamicMetaObject /*!*/ GetInstance(Expression /*!*/ instance, Type /*!*/ testType)
        {
            Assert.NotNull(instance, testType);
            object instanceValue = Value.BindingSelf;

            BindingRestrictions restrictions = BindingRestrictionsHelpers.GetRuntimeTypeRestriction(instance, testType);

            // cast the instance to the correct type
            if (CompilerHelpers.IsStrongBox(instanceValue))
            {
                instance      = ReadStrongBoxValue(instance);
                instanceValue = ((IStrongBox)instanceValue).Value;
            }
            else if (!testType.IsEnum)
            {
                // We need to deal w/ wierd types like MarshalByRefObject.
                // We could have an MBRO whos DeclaringType is completely different.
                // Therefore we special case it here and cast to the declaring type

                Type selfType = CompilerHelpers.GetType(Value.BindingSelf);
                selfType = CompilerHelpers.GetVisibleType(selfType);

                if (selfType == typeof(object) && Value.DeclaringType.IsInterface)
                {
                    selfType = Value.DeclaringType;

                    Type genericTypeDefinition = null;
                    if (Value.DeclaringType.IsGenericType &&
                        Value.DeclaringType.FullName == null &&
                        Value.DeclaringType.ContainsGenericParameters &&
                        !Value.DeclaringType.IsGenericTypeDefinition)
                    {
                        // from MSDN: If the current type contains generic type parameters that have not been replaced by
                        // specific types (that is, the ContainsGenericParameters property returns true), but the type
                        // is not a generic type definition (that is, the IsGenericTypeDefinition property returns false),
                        // this property returns Nothing. For example, consider the classes Base and Derived in the following code.

                        // if this type is completely generic (no type arguments specified) then we'll go ahead and get the
                        // generic type definition for the this parameter - that'll let us successfully type infer on it later.
                        var  genericArgs     = Value.DeclaringType.GetGenericArguments();
                        bool hasOnlyGenerics = genericArgs.Length > 0;
                        foreach (var genericParam in genericArgs)
                        {
                            if (!genericParam.IsGenericParameter)
                            {
                                hasOnlyGenerics = false;
                                break;
                            }
                        }
                        if (hasOnlyGenerics)
                        {
                            genericTypeDefinition = Value.DeclaringType.GetGenericTypeDefinition();
                        }
                    }
                    else if (Value.DeclaringType.IsGenericTypeDefinition)
                    {
                        genericTypeDefinition = Value.DeclaringType;
                    }

                    if (genericTypeDefinition != null)
                    {
                        // we're a generic interface method on a non-public type.
                        // We need to see if we can match any types implemented on
                        // the concrete selfType.
                        var interfaces = CompilerHelpers.GetType(Value.BindingSelf).GetInterfaces();
                        foreach (var iface in interfaces)
                        {
                            if (iface.IsGenericType && iface.GetGenericTypeDefinition() == genericTypeDefinition)
                            {
                                selfType = iface;
                                break;
                            }
                        }
                    }
                }

                if (Value.DeclaringType.IsInterface && selfType.IsValueType)
                {
                    // explicit interface implementation dispatch on a value type, don't
                    // unbox the value type before the dispatch.
                    instance = AstUtils.Convert(instance, Value.DeclaringType);
                }
                else if (selfType.IsValueType)
                {
                    // We might be calling a a mutating method (like
                    // Rectangle.Intersect). If so, we want it to mutate
                    // the boxed value directly
                    instance = Ast.Unbox(instance, selfType);
                }
                else
                {
#if SILVERLIGHT
                    instance = AstUtils.Convert(instance, selfType);
#else
                    Type convType = selfType == typeof(MarshalByRefObject) ? CompilerHelpers.GetVisibleType(Value.DeclaringType) : selfType;

                    instance = AstUtils.Convert(instance, convType);
#endif
                }
            }
            else
            {
                // we don't want to cast the enum to its real type, it will unbox it
                // and turn it into its underlying type.  We presumably want to call
                // a method on the Enum class though - so we cast to Enum instead.
                instance = AstUtils.Convert(instance, typeof(Enum));
            }
            return(new DynamicMetaObject(
                       instance,
                       restrictions,
                       instanceValue
                       ));
        }