private MethodBindResult BindMethodUsingReflection(BindingFlags bindFlags, HostTarget hostTarget, string name, Type[] typeArgs, object[] args)
        {
            // ReSharper disable CoVariantArrayConversion

            var candidates = GetReflectionCandidates(bindFlags, hostTarget, name, typeArgs).Distinct().ToArray();

            if (candidates.Length > 0)
            {
                try
                {
                    object state;
                    var    rawResult = Type.DefaultBinder.BindToMethod(bindFlags, candidates, ref args, null, null, null, out state);
                    return(MethodBindResult.Create(name, rawResult, hostTarget, args));
                }
                catch (MissingMethodException)
                {
                }
                catch (AmbiguousMatchException)
                {
                }
            }

            return(new MethodBindFailure(() => new MissingMemberException(MiscHelpers.FormatInvariant("Object has no method named '{0}' that matches the specified arguments", name))));

            // ReSharper restore CoVariantArrayConversion
        }
Example #2
0
        internal HostItem GetOrCreateHostItem(HostTarget target, HostItemFlags flags, Func <ScriptEngine, HostTarget, HostItemFlags, HostItem> createHostItem)
        {
            var hostObject = target as HostObject;

            if (hostObject != null)
            {
                return(GetOrCreateHostItemForHostTarget(hostObject, flags, createHostItem));
            }

            var hostType = target as HostType;

            if (hostType != null)
            {
                return(GetOrCreateHostItemForHostType(hostType, flags, createHostItem));
            }

            var hostMethod = target as HostMethod;

            if (hostMethod != null)
            {
                return(GetOrCreateHostItemForHostTarget(hostMethod, flags, createHostItem));
            }

            var hostIndexedProperty = target as HostIndexedProperty;

            if (hostIndexedProperty != null)
            {
                return(GetOrCreateHostItemForHostTarget(hostIndexedProperty, flags, createHostItem));
            }

            return(createHostItem(this, target, flags));
        }
Example #3
0
        private static HostItem Create(ScriptEngine engine, HostTarget target, HostItemFlags flags)
        {
            if (!MiscHelpers.PlatformIsWindows())
            {
                return(new HostItem(engine, target, flags));
            }

            return(TargetSupportsExpandoMembers(target, flags) ? new DispatchExHostItem(engine, target, flags) : new HostItem(engine, target, flags));
        }
Example #4
0
        public BindSignature(HostTarget target, string name, Type[] typeArgs, object[] args)
        {
            targetInfo    = new TargetInfo(target);
            this.typeArgs = typeArgs;
            this.name     = name;

            argData = new ArgInfo[args.Length];
            for (var index = 0; index < args.Length; index++)
            {
                argData[index] = new ArgInfo(args[index]);
            }
        }
Example #5
0
        public BindSignature(Type context, BindingFlags flags, HostTarget target, string name, Type[] typeArgs, object[] args)
        {
            this.context  = context;
            this.flags    = flags;
            targetInfo    = new TargetInfo(target);
            this.name     = name;
            this.typeArgs = typeArgs;

            argData = new ArgInfo[args.Length];
            for (var index = 0; index < args.Length; index++)
            {
                argData[index] = new ArgInfo(args[index]);
            }
        }
            public static MethodBindResult Create(string name, object rawResult, HostTarget hostTarget, object[] args)
            {
                var method = rawResult as MethodInfo;

                if (method != null)
                {
                    if ((method.IsStatic) && !hostTarget.Flags.HasFlag(HostTargetFlags.AllowStaticMembers))
                    {
                        return(new MethodBindFailure(() => new InvalidOperationException(MiscHelpers.FormatInvariant("Cannot access static method '{0}' in non-static context", method.Name))));
                    }

                    return(new MethodBindSuccess(hostTarget, method, args));
                }

                return(new MethodBindFailure((rawResult as Func <Exception>) ?? (() => new NotSupportedException(MiscHelpers.FormatInvariant("Invocation of method '{0}' failed (unrecognized binding)", name)))));
            }
        private static IEnumerable <CSharpArgumentInfo> CreateArgInfoEnum(HostTarget target, object[] args)
        {
            if (target is HostType)
            {
                yield return(CreateStaticTypeArgInfo());
            }
            else
            {
                yield return(CreateArgInfo(target.DynamicInvokeTarget));
            }

            foreach (var arg in args)
            {
                yield return(CreateArgInfo(arg));
            }
        }
Example #8
0
        private HostItem GetOrCreateHostItemForHostTarget(HostTarget hostTarget, HostItemFlags flags, Func <ScriptEngine, HostTarget, HostItemFlags, HostItem> createHostItem)
        {
            var cacheEntry = hostObjectHostItemCache.GetOrCreateValue(hostTarget.Target);

            List <WeakReference> activeWeakRefs = null;
            var staleWeakRefCount = 0;

            foreach (var weakRef in cacheEntry)
            {
                var hostItem = weakRef.Target as HostItem;
                if (hostItem == null)
                {
                    staleWeakRefCount++;
                }
                else
                {
                    if ((hostItem.Target.Type == hostTarget.Type) && (hostItem.Flags == flags))
                    {
                        return(hostItem);
                    }

                    if (activeWeakRefs == null)
                    {
                        activeWeakRefs = new List <WeakReference>(cacheEntry.Count);
                    }

                    activeWeakRefs.Add(weakRef);
                }
            }

            if (staleWeakRefCount > 4)
            {
                cacheEntry.Clear();
                if (activeWeakRefs != null)
                {
                    cacheEntry.Capacity = activeWeakRefs.Count + 1;
                    cacheEntry.AddRange(activeWeakRefs);
                }
            }

            var newHostItem = createHostItem(this, hostTarget, flags);

            cacheEntry.Add(new WeakReference(newHostItem));
            return(newHostItem);
        }
        private static bool TargetSupportsExpandoMembers(HostTarget target, HostItemFlags flags)
        {
            if (!TargetSupportsSpecialTargets(target))
            {
                return(false);
            }

            if (typeof(IDynamic).IsAssignableFrom(target.Type))
            {
                return(true);
            }

            if (target is IHostVariable)
            {
                if (target.Type.IsImport)
                {
                    return(true);
                }
            }
            else
            {
                if ((target.InvokeTarget is IDispatchEx dispatchEx) && dispatchEx.GetType().IsCOMObject)
                {
                    return(true);
                }
            }

            if (typeof(IPropertyBag).IsAssignableFrom(target.Type))
            {
                return(true);
            }

            if (!flags.HasFlag(HostItemFlags.HideDynamicMembers) && typeof(IDynamicMetaObjectProvider).IsAssignableFrom(target.Type))
            {
                return(true);
            }

            return(false);
        }
Example #10
0
            public TargetInfo(HostTarget target)
            {
                if (target is HostType)
                {
                    kind       = TargetKind.Static;
                    targetType = target.Type;
                }
                else if (target.InvokeTarget == null)
                {
                    kind       = TargetKind.Null;
                    targetType = target.Type;
                }
                else
                {
                    kind       = TargetKind.Instance;
                    targetType = target.Type;

                    var tempType = target.InvokeTarget.GetType();
                    if (tempType != targetType)
                    {
                        instanceType = tempType;
                    }
                }
            }
        private static MethodBindResult BindMethodCore(Type bindContext, BindingFlags bindFlags, HostTarget target, string name, Type[] typeArgs, object[] args, object[] bindArgs)
        {
            Interlocked.Increment(ref coreBindCount);

            // create C# member invocation binder
            const CSharpBinderFlags binderFlags = CSharpBinderFlags.InvokeSimpleName | CSharpBinderFlags.ResultDiscarded;
            var binder = (InvokeMemberBinder)Binder.InvokeMember(binderFlags, name, typeArgs, bindContext, CreateArgInfoEnum(target, bindArgs));

            // perform default binding
            var rawResult = BindMethodRaw(bindFlags, binder, target, bindArgs);

            var result = MethodBindResult.Create(name, rawResult, target, args);
            if ((result is MethodBindFailure) && !(target is HostType) && target.Type.IsInterface)
            {
                // binding through interface failed; try base interfaces
                foreach (var interfaceType in target.Type.GetInterfaces())
                {
                    var baseInterfaceTarget = HostObject.Wrap(target.InvokeTarget, interfaceType);
                    rawResult = BindMethodRaw(bindFlags, binder, baseInterfaceTarget, bindArgs);

                    var baseInterfaceResult = MethodBindResult.Create(name, rawResult, target, args);
                    if (baseInterfaceResult is MethodBindSuccess)
                    {
                        return baseInterfaceResult;
                    }
                }

                // binding through base interfaces failed; try System.Object
                var objectTarget = HostObject.Wrap(target.InvokeTarget, typeof(object));
                rawResult = BindMethodRaw(bindFlags, binder, objectTarget, bindArgs);

                var objectResult = MethodBindResult.Create(name, rawResult, target, args);
                if (objectResult is MethodBindSuccess)
                {
                    return objectResult;
                }
            }

            return result;
        }
        private static object BindMethodRaw(BindingFlags bindFlags, InvokeMemberBinder binder, HostTarget target, object[] bindArgs)
        {
            var expr = DynamicHelpers.Bind(binder, target, bindArgs).Expression;

            if (expr == null)
            {
                return(new Func <Exception>(() => new MissingMemberException(MiscHelpers.FormatInvariant("Object has no method named '{0}'", binder.Name))));
            }

            if (expr.NodeType == ExpressionType.Dynamic)
            {
                // The binding result is a dynamic call, which is indicative of COM interop. This
                // sort of binding is not very useful here; it can't be resolved to a MethodInfo
                // instance, and caching it is problematic because it includes argument bindings.
                // Falling back to reflection should work in most cases because COM interfaces
                // support neither generic nor overloaded methods.

                try
                {
                    var method = target.Type.GetMethod(binder.Name, bindFlags);
                    return((object)method ?? new Func <Exception>(() => new MissingMemberException(MiscHelpers.FormatInvariant("Object has no method named '{0}'", binder.Name))));
                }
                catch (AmbiguousMatchException exception)
                {
                    return(new Func <Exception>(() => new AmbiguousMatchException(exception.Message)));
                }
            }

            return((new MethodBindingVisitor(target.InvokeTarget, binder.Name, expr)).Result);
        }
        private static MethodBindResult BindMethodCore(Type bindContext, BindingFlags bindFlags, HostTarget target, string name, Type[] typeArgs, object[] args, object[] bindArgs)
        {
            Interlocked.Increment(ref coreBindCount);

            // create C# member invocation binder
            const CSharpBinderFlags binderFlags = CSharpBinderFlags.InvokeSimpleName | CSharpBinderFlags.ResultDiscarded;
            var binder = (InvokeMemberBinder)Binder.InvokeMember(binderFlags, name, typeArgs, bindContext, CreateArgInfoEnum(target, bindArgs));

            // perform default binding
            var rawResult = BindMethodRaw(bindFlags, binder, target, bindArgs);

            var result = MethodBindResult.Create(name, rawResult, target, args);

            if ((result is MethodBindFailure) && !(target is HostType) && target.Type.IsInterface)
            {
                // binding through interface failed; try base interfaces
                foreach (var interfaceType in target.Type.GetInterfaces())
                {
                    var baseInterfaceTarget = HostObject.Wrap(target.InvokeTarget, interfaceType);
                    rawResult = BindMethodRaw(bindFlags, binder, baseInterfaceTarget, bindArgs);

                    var baseInterfaceResult = MethodBindResult.Create(name, rawResult, target, args);
                    if (baseInterfaceResult is MethodBindSuccess)
                    {
                        return(baseInterfaceResult);
                    }
                }

                // binding through base interfaces failed; try System.Object
                var objectTarget = HostObject.Wrap(target.InvokeTarget, typeof(object));
                rawResult = BindMethodRaw(bindFlags, binder, objectTarget, bindArgs);

                var objectResult = MethodBindResult.Create(name, rawResult, target, args);
                if (objectResult is MethodBindSuccess)
                {
                    return(objectResult);
                }
            }

            return(result);
        }
        private static MethodBindResult BindMethodInternal(Type bindContext, BindingFlags bindFlags, HostTarget target, string name, Type[] typeArgs, object[] args, object[] bindArgs)
        {
            // WARNING: BindSignature holds on to the specified typeArgs; subsequent modification
            // will result in bugs that are difficult to diagnose. Create a copy if necessary.

            var signature = new BindSignature(bindContext, bindFlags, target, name, typeArgs, bindArgs);
            MethodBindResult result;

            object rawResult;

            if (coreBindCache.TryGetValue(signature, out rawResult))
            {
                result = MethodBindResult.Create(name, rawResult, target, args);
            }
            else
            {
                result = BindMethodCore(bindContext, bindFlags, target, name, typeArgs, args, bindArgs);
                coreBindCache.TryAdd(signature, result.RawResult);
            }

            return(result);
        }
        private static MethodBindResult BindMethodInternal(Type bindContext, BindingFlags bindFlags, HostTarget target, string name, Type[] typeArgs, object[] args, object[] bindArgs)
        {
            // WARNING: BindSignature holds on to the specified typeArgs; subsequent modification
            // will result in bugs that are difficult to diagnose. Create a copy if necessary.

            var signature = new BindSignature(bindContext, bindFlags, target, name, typeArgs, bindArgs);
            MethodBindResult result;

            object rawResult;
            if (coreBindCache.TryGetValue(signature, out rawResult))
            {
                result = MethodBindResult.Create(name, rawResult, target, args);
            }
            else
            {
                result = BindMethodCore(bindContext, bindFlags, target, name, typeArgs, args, bindArgs);
                coreBindCache.TryAdd(signature, result.RawResult);
            }

            return result;
        }
 private static HostItem Create(ScriptEngine engine, HostTarget target, HostItemFlags flags)
 {
     return(TargetSupportsExpandoMembers(target, flags) ? new DispatchExHostItem(engine, target, flags) : new HostItem(engine, target, flags));
 }
 public MethodBindSuccess(HostTarget hostTarget, MethodInfo method, object[] args)
 {
     this.hostTarget = hostTarget;
     this.method = method;
     this.args = args;
 }
            public static MethodBindResult Create(string name, object rawResult, HostTarget hostTarget, object[] args)
            {
                var method = rawResult as MethodInfo;
                if (method != null)
                {
                    if ((method.IsStatic) && !hostTarget.Flags.HasFlag(HostTargetFlags.AllowStaticMembers))
                    {
                        return new MethodBindFailure(() => new InvalidOperationException(MiscHelpers.FormatInvariant("Cannot access static method '{0}' in non-static context", method.Name)));
                    }

                    return new MethodBindSuccess(hostTarget, method, args);
                }

                return new MethodBindFailure((rawResult as Func<Exception>) ?? (() => new NotSupportedException(MiscHelpers.FormatInvariant("Invocation of method '{0}' failed (unrecognized binding)", name))));
            }
        private static IEnumerable<CSharpArgumentInfo> CreateArgInfoEnum(HostTarget target, object[] args)
        {
            if (target is HostType)
            {
                yield return CreateStaticTypeArgInfo();
            }
            else
            {
                yield return CreateArgInfo(target.DynamicInvokeTarget);
            }

            foreach (var arg in args)
            {
                yield return CreateArgInfo(arg);
            }
        }
        private MethodBindResult BindMethodUsingReflection(BindingFlags bindFlags, HostTarget hostTarget, string name, Type[] typeArgs, object[] args)
        {
            // ReSharper disable CoVariantArrayConversion

            var candidates = GetReflectionCandidates(bindFlags, hostTarget, name, typeArgs).Distinct().ToArray();
            if (candidates.Length > 0)
            {
                try
                {
                    object state;
                    var rawResult = Type.DefaultBinder.BindToMethod(bindFlags, candidates, ref args, null, null, null, out state);
                    return MethodBindResult.Create(name, rawResult, hostTarget, args);
                }
                catch (MissingMethodException)
                {
                }
                catch (AmbiguousMatchException)
                {
                }
            }

            return new MethodBindFailure(() => new MissingMemberException(MiscHelpers.FormatInvariant("Object has no method named '{0}' that matches the specified arguments", name)));

            // ReSharper restore CoVariantArrayConversion
        }
Example #21
0
 public DispatchExHostItem(ScriptEngine engine, HostTarget target, HostItemFlags flags)
     : base(engine, target, flags)
 {
     EnsurePatched();
 }
Example #22
0
 private static HostItem Create(ScriptEngine engine, HostTarget target, HostItemFlags flags)
 {
     return(new HostItem(engine, target, flags));
 }
        private static object BindMethodRaw(BindingFlags bindFlags, InvokeMemberBinder binder, HostTarget target, object[] bindArgs)
        {
            var expr = DynamicHelpers.Bind(binder, target, bindArgs).Expression;
            if (expr == null)
            {
                return new Func<Exception>(() => new MissingMemberException(MiscHelpers.FormatInvariant("Object has no method named '{0}'", binder.Name)));
            }

            if (expr.NodeType == ExpressionType.Dynamic)
            {
                // The binding result is a dynamic call, which is indicative of COM interop. This
                // sort of binding is not very useful here; it can't be resolved to a MethodInfo
                // instance, and caching it is problematic because it includes argument bindings.
                // Falling back to reflection should work in most cases because COM interfaces
                // support neither generic nor overloaded methods.

                try
                {
                    var method = target.Type.GetMethod(binder.Name, bindFlags);
                    return (object)method ?? new Func<Exception>(() => new MissingMemberException(MiscHelpers.FormatInvariant("Object has no method named '{0}'", binder.Name)));
                }
                catch (AmbiguousMatchException exception)
                {
                    return new Func<Exception>(() => new AmbiguousMatchException(exception.Message));
                }
            }

            return (new MethodBindingVisitor(target.InvokeTarget, binder.Name, expr)).Result;
        }
        private IEnumerable <MethodInfo> GetReflectionCandidates(BindingFlags bindFlags, HostTarget hostTarget, string name, Type[] typeArgs)
        {
            foreach (var method in GetReflectionCandidates(bindFlags, hostTarget.Type, name, typeArgs))
            {
                yield return(method);
            }

            if (!(hostTarget is HostType) && hostTarget.Type.IsInterface)
            {
                foreach (var interfaceType in hostTarget.Type.GetInterfaces())
                {
                    foreach (var method in GetReflectionCandidates(bindFlags, interfaceType, name, typeArgs))
                    {
                        yield return(method);
                    }
                }

                foreach (var method in GetReflectionCandidates(bindFlags, typeof(object), name, typeArgs))
                {
                    yield return(method);
                }
            }
        }
        private IEnumerable<MethodInfo> GetReflectionCandidates(BindingFlags bindFlags, HostTarget hostTarget, string name, Type[] typeArgs)
        {
            foreach (var method in GetReflectionCandidates(bindFlags, hostTarget.Type, name, typeArgs))
            {
                yield return method;
            }

            if (!(hostTarget is HostType) && hostTarget.Type.IsInterface)
            {
                foreach (var interfaceType in hostTarget.Type.GetInterfaces())
                {
                    foreach (var method in GetReflectionCandidates(bindFlags, interfaceType, name, typeArgs))
                    {
                        yield return method;
                    }
                }

                foreach (var method in GetReflectionCandidates(bindFlags, typeof(object), name, typeArgs))
                {
                    yield return method;
                }
            }
        }
 public MethodBindSuccess(HostTarget hostTarget, MethodInfo method, object[] args)
 {
     this.hostTarget = hostTarget;
     this.method     = method;
     this.args       = args;
 }
            // ReSharper disable MemberCanBeProtected.Local

            public ExpandoHostItem(ScriptEngine engine, HostTarget target, HostItemFlags flags)
                : base(engine, target, flags)
            {
            }