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 }
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)); }
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)); }
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]); } }
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)); } }
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); }
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 }
public DispatchExHostItem(ScriptEngine engine, HostTarget target, HostItemFlags flags) : base(engine, target, flags) { EnsurePatched(); }
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) { }