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