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
        }
Exemple #2
0
        private MethodBindResult BindMethod(string name, Type[] typeArgs, object[] args, object[] bindArgs)
        {
            var bindContext = GetEffectiveAccessContext();
            var bindFlags   = GetMethodBindFlags();

            // 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 (engine.TryGetCachedBindResult(signature, out rawResult))
            {
                result = MethodBindResult.Create(name, rawResult, target, args);
            }
            else
            {
                result = BindMethodInternal(bindContext, bindFlags, target, name, typeArgs, args, bindArgs);
                if (!result.IsPreferredMethod(name))
                {
                    if (result is MethodBindSuccess)
                    {
                        result = new MethodBindFailure(() => new MissingMemberException(MiscHelpers.FormatInvariant("Object has no method named '{0}' that matches the specified arguments", name)));
                    }

                    foreach (var altName in GetAltMethodNames(name, bindFlags))
                    {
                        var altResult = BindMethodInternal(bindContext, bindFlags, target, altName, typeArgs, args, bindArgs);
                        if (altResult.IsUnblockedMethod())
                        {
                            result = altResult;
                            break;
                        }
                    }
                }

                if ((result is MethodBindFailure) && engine.UseReflectionBindFallback)
                {
                    var reflectionResult = BindMethodUsingReflection(bindFlags, target, name, typeArgs, args);
                    if (reflectionResult is MethodBindSuccess)
                    {
                        result = reflectionResult;
                    }
                }

                engine.CacheBindResult(signature, result.RawResult);
            }

            return(result);
        }
Exemple #3
0
        private MethodBindResult BindMethodInternal(string name, Type[] typeArgs, object[] args, object[] bindArgs)
        {
            // create C# member invocation binder
            const CSharpBinderFlags binderFlags = CSharpBinderFlags.InvokeSimpleName | CSharpBinderFlags.ResultDiscarded;
            var binder = Binder.InvokeMember(binderFlags, name, typeArgs, accessContext ?? engine.AccessContext, CreateArgInfoEnum(bindArgs));

            // perform default binding
            var binding   = DynamicHelpers.Bind((DynamicMetaObjectBinder)binder, target, bindArgs);
            var rawResult = (new MethodBindingVisitor(target.InvokeTarget, name, binding.Expression)).Result;

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

            if (!(result is MethodBindSuccess) && !(target is HostType) && target.Type.IsInterface)
            {
                // binding through interface failed; try base interfaces
                foreach (var interfaceType in target.Type.GetInterfaces())
                {
                    var tempTarget = HostObject.Wrap(target.InvokeTarget, interfaceType);
                    binding   = DynamicHelpers.Bind((DynamicMetaObjectBinder)binder, tempTarget, bindArgs);
                    rawResult = (new MethodBindingVisitor(target.InvokeTarget, name, binding.Expression)).Result;

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

                // binding through base interfaces failed; try System.Object
                var objectTarget = HostObject.Wrap(target.InvokeTarget, typeof(object));
                binding   = DynamicHelpers.Bind((DynamicMetaObjectBinder)binder, objectTarget, bindArgs);
                rawResult = (new MethodBindingVisitor(target.InvokeTarget, name, binding.Expression)).Result;

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

            return(result);
        }
Exemple #4
0
        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;

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

            return(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);
        }