public override DynamicMetaObject FallbackCreateInstance(DynamicMetaObject target, DynamicMetaObject[] args, DynamicMetaObject errorSuggestion)
        {
            Type typeToUse = target.Value is Type ? (Type)target.Value : target.LimitType;

            IList <DynamicMetaObject> argsPlus = new List <DynamicMetaObject>(args.Length);

            foreach (DynamicMetaObject arg in args)
            {
                argsPlus.Add(arg);
            }

            OverloadResolverFactory factory = _context.SharedOverloadResolverFactory;
            DefaultOverloadResolver res     = factory.CreateOverloadResolver(argsPlus, new CallSignature(args.Length), CallTypes.None);

            BindingFlags       flags   = BindingFlags.Public | BindingFlags.Instance;
            IList <MethodBase> methods = new List <MethodBase>(typeToUse.GetConstructors(flags).Where <MethodBase>(x => x.GetParameters().Length == args.Length));

            if (methods.Count > 0)
            {
                BindingTarget     bt;
                DynamicMetaObject dmo = _context.Binder.CallMethod(res, methods, BindingRestrictions.Empty, "_ctor", NarrowingLevel.None, NarrowingLevel.All, out bt);
                dmo = DynUtils.MaybeBoxReturnValue(dmo);
                return(dmo);
            }

            return(errorSuggestion ??
                   new DynamicMetaObject(
                       Expression.Throw(
                           Expression.New(typeof(MissingMethodException).GetConstructor(new Type[] { typeof(string) }),
                                          Expression.Constant("Cannot find constructor matching args")),
                           typeof(object)),
                       target.Restrictions.Merge(BindingRestrictions.Combine(args))));
        }
        public override DynamicMetaObject FallbackInvokeMember(DynamicMetaObject target, DynamicMetaObject[] args, DynamicMetaObject errorSuggestion)
        {
            if (target.HasValue && target.Value == null)
            {
                return(errorSuggestion ??
                       new DynamicMetaObject(
                           Expression.Throw(
                               Expression.New(typeof(MissingMethodException).GetConstructor(new Type[] { typeof(string) }),
                                              Expression.Constant(String.Format("Cannot call {0} method named {1} on nil", _isStatic ? "static" : "instance", this.Name))),
                               typeof(object)),
                           BindingRestrictions.GetInstanceRestriction(target.Expression, null)));
            }



            Type typeToUse = _isStatic && target.Value is Type ? (Type)target.Value : target.LimitType;


            IList <DynamicMetaObject> argsPlus = new List <DynamicMetaObject>(args.Length + (_isStatic ? 0 : 1));

            if (!_isStatic)
            {
                argsPlus.Add(target);
            }
            foreach (DynamicMetaObject arg in args)
            {
                argsPlus.Add(arg);
            }

            OverloadResolverFactory factory = _context.SharedOverloadResolverFactory;
            DefaultOverloadResolver res     = factory.CreateOverloadResolver(argsPlus, new CallSignature(args.Length), _isStatic ? CallTypes.None : CallTypes.ImplicitInstance);

            BindingFlags       flags   = BindingFlags.InvokeMethod | BindingFlags.Public | (_isStatic ? BindingFlags.Static : BindingFlags.Instance);
            IList <MethodBase> methods = new List <MethodBase>(typeToUse.GetMethods(flags).Where <MethodBase>(x => x.Name == Name && x.GetParameters().Length == args.Length));

            if (methods.Count > 0)
            {
                BindingTarget     bt;
                DynamicMetaObject dmo = _context.Binder.CallMethod(
                    res,
                    methods,
                    target.Restrictions.Merge(BindingRestrictionsHelpers.GetRuntimeTypeRestriction(target).Merge(BindingRestrictions.Combine(args))),
                    Name,
                    NarrowingLevel.None,
                    NarrowingLevel.All,
                    out bt);
                dmo = DynUtils.MaybeBoxReturnValue(dmo);

                //; Console.WriteLine(dmo.Expression.DebugView);
                return(dmo);
            }

            return(errorSuggestion ??
                   new DynamicMetaObject(
                       Expression.Throw(
                           Expression.New(typeof(MissingMethodException).GetConstructor(new Type[] { typeof(string) }),
                                          Expression.Constant(String.Format("No matching member {0} taking {1} args for {2}", this.Name, args.Length, typeToUse.Name))),
                           typeof(object)),
                       target.Restrictions.Merge(BindingRestrictionsHelpers.GetRuntimeTypeRestriction(target).Merge(BindingRestrictions.Combine(args)))));
        }
        public override DynamicMetaObject FallbackGetMember(DynamicMetaObject target, DynamicMetaObject errorSuggestion)
        {
            if (target.HasValue && target.Value == null)
            {
                return(errorSuggestion ??
                       new DynamicMetaObject(
                           Expression.Throw(
                               Expression.New(typeof(MissingMethodException).GetConstructor(new Type[] { typeof(string) }),
                                              Expression.Constant(String.Format("Cannot call {0} field/property/member name {1} on nil", _isStatic ? "static" : "instance", this.Name))),
                               typeof(object)),
                           BindingRestrictions.GetInstanceRestriction(target.Expression, null)));
            }

            Expression instanceExpr = _isStatic ? null : Expression.Convert(target.Expression, target.LimitType);
            Type       typeToUse    = _isStatic && target.Value is Type ? (Type)target.Value : target.LimitType;

            BindingRestrictions restrictions = target.Restrictions.Merge(BindingRestrictions.GetTypeRestriction(target.Expression, target.LimitType));
            BindingFlags        flags        = BindingFlags.Public;

            if (_isStatic)
            {
                flags |= BindingFlags.Static;
            }
            else
            {
                flags |= BindingFlags.Instance;
            }

            FieldInfo finfo = typeToUse.GetField(Name, flags);

            if (finfo != null)
            {
                return(DynUtils.MaybeBoxReturnValue(new DynamicMetaObject(Expression.Field(instanceExpr, finfo), restrictions)));
            }

            PropertyInfo pinfo = typeToUse.GetProperty(Name, flags);

            if (pinfo != null)
            {
                return(DynUtils.MaybeBoxReturnValue(new DynamicMetaObject(Expression.Property(instanceExpr, pinfo), restrictions)));
            }

            MethodInfo minfo = typeToUse.GetMethod(Name, flags, Type.DefaultBinder, Type.EmptyTypes, new ParameterModifier[0]);

            if (minfo != null)
            {
                return(DynUtils.MaybeBoxReturnValue(new DynamicMetaObject(Expression.Call(instanceExpr, minfo), restrictions)));
            }

            return(errorSuggestion ??
                   new DynamicMetaObject(
                       Expression.Throw(
                           Expression.New(typeof(MissingMethodException).GetConstructor(new Type[] { typeof(string) }),
                                          Expression.Constant(String.Format("Cannot find {0} field/property/member name {1}", _isStatic ? "static" : "instance", this.Name))),
                           typeof(object)),
                       target.Restrictions.Merge(BindingRestrictionsHelpers.GetRuntimeTypeRestriction(target))));
        }