@@ -76,28 +76,33 @@ internal partial class HostItem
7676 {
7777 #region internal members
7878
79- private object InvokeMethod ( string name , object [ ] args )
79+ private object InvokeMethod ( string name , object [ ] args , object [ ] bindArgs )
8080 {
8181 var typeArgs = GetTypeArgs ( args ) . ToArray ( ) ;
8282 if ( typeArgs . Length > 0 )
8383 {
8484 args = args . Skip ( typeArgs . Length ) . ToArray ( ) ;
85+ bindArgs = bindArgs . Skip ( typeArgs . Length ) . ToArray ( ) ;
8586 }
8687
87- return InvokeMethod ( name , typeArgs , args ) ;
88+ return InvokeMethod ( name , typeArgs , args , bindArgs ) ;
8889 }
8990
90- private object InvokeMethod ( string name , Type [ ] typeArgs , object [ ] args )
91+ private object InvokeMethod ( string name , Type [ ] typeArgs , object [ ] args , object [ ] bindArgs )
9192 {
92- var bindResult = BindMethod ( name , typeArgs , args ) ;
93+ var bindResult = BindMethod ( name , typeArgs , args , bindArgs ) ;
9394 if ( ( bindResult is MethodBindFailure ) && target . Flags . HasFlag ( HostTargetFlags . AllowExtensionMethods ) )
9495 {
95- var targetArg = new [ ] { target . DynamicInvokeTarget } ;
96+ var targetArg = new [ ] { target . Target } ;
9697 var extensionArgs = targetArg . Concat ( args ) . ToArray ( ) ;
98+
99+ var targetBindArg = new object [ ] { target } ;
100+ var extensionBindArgs = targetBindArg . Concat ( bindArgs ) . ToArray ( ) ;
101+
97102 foreach ( var type in cachedExtensionMethodSummary . Types )
98103 {
99104 var extensionHostItem = ( HostItem ) Wrap ( engine , HostType . Wrap ( type ) ) ;
100- var extensionBindResult = extensionHostItem . BindMethod ( name , typeArgs , extensionArgs ) ;
105+ var extensionBindResult = extensionHostItem . BindMethod ( name , typeArgs , extensionArgs , extensionBindArgs ) ;
101106 if ( extensionBindResult is MethodBindSuccess )
102107 {
103108 return extensionBindResult . Invoke ( engine ) ;
@@ -128,67 +133,73 @@ private static IEnumerable<Type> GetTypeArgs(object[] args)
128133 }
129134 }
130135
131- private MethodBindResult BindMethod ( string name , Type [ ] typeArgs , object [ ] args )
136+ private MethodBindResult BindMethod ( string name , Type [ ] typeArgs , object [ ] args , object [ ] bindArgs )
132137 {
133- MethodBindResult result = null ;
134-
135138 // WARNING: BindSignature holds on to the specified typeArgs; subsequent modification
136139 // will result in bugs that are difficult to diagnose. Create a copy if necessary.
137140
141+ var signature = new BindSignature ( target , name , typeArgs , bindArgs ) ;
142+ MethodBindResult result ;
143+
138144 object rawResult ;
139- var signature = new BindSignature ( target , name , typeArgs , args ) ;
140145 if ( engine . TryGetCachedBindResult ( signature , out rawResult ) )
141146 {
142147 result = MethodBindResult . Create ( name , rawResult , target , args ) ;
143148 }
144149 else
145150 {
146- var entryList = new List < MethodBindEntry > ( ) ;
147- if ( ( target is HostType ) || ( target . InvokeTarget == null ) || ! target . Type . IsInterface )
151+ result = BindMethodInternal ( name , typeArgs , args , bindArgs ) ;
152+ if ( ! result . IsPreferredMethod ( name ) )
148153 {
149- entryList . Add ( new MethodBindEntry ( name , accessContext ?? engine . AccessContext ) ) ;
150- }
151- else
152- {
153- foreach ( var mapping in target . InvokeTarget . GetType ( ) . ExtGetInterfaceMaps ( target . Type ) )
154- {
155- for ( var index = 0 ; index < mapping . InterfaceMethods . Length ; index ++ )
156- {
157- if ( mapping . InterfaceMethods [ index ] . Name == name )
158- {
159- var targetMethod = mapping . TargetMethods [ index ] ;
160- entryList . Add ( new MethodBindEntry ( targetMethod . Name , targetMethod . DeclaringType ) ) ;
161- }
162- }
163- }
164-
165- if ( entryList . Count < 1 )
154+ if ( result is MethodBindSuccess )
166155 {
167- entryList . Add ( new MethodBindEntry ( name , accessContext ?? engine . AccessContext ) ) ;
156+ result = new MethodBindFailure ( new MissingMemberException ( MiscHelpers . FormatInvariant ( "Object has no method named '{0}' that matches the specified arguments" , name ) ) ) ;
168157 }
169- }
170-
171- foreach ( var entry in entryList )
172- {
173- const CSharpBinderFlags binderFlags = CSharpBinderFlags . InvokeSimpleName | CSharpBinderFlags . ResultDiscarded ;
174- var binder = Binder . InvokeMember ( binderFlags , entry . Name , typeArgs , entry . AccessContext , CreateArgInfoEnum ( args ) ) ;
175158
176- var binding = DynamicHelpers . Bind ( ( DynamicMetaObjectBinder ) binder , target . DynamicInvokeTarget , args ) ;
177- rawResult = ( new MethodBindingVisitor ( target . InvokeTarget , entry . Name , binding . Expression ) ) . Result ;
178- result = MethodBindResult . Create ( entry . Name , rawResult , target , args ) ;
179- if ( result is MethodBindSuccess )
159+ foreach ( var altName in GetAltMethodNames ( name ) )
180160 {
181- break ;
161+ var altResult = BindMethodInternal ( altName , typeArgs , args , bindArgs ) ;
162+ if ( altResult . IsUnblockedMethod ( ) )
163+ {
164+ result = altResult ;
165+ break ;
166+ }
182167 }
183168 }
184169
185- Debug . Assert ( rawResult != null ) ;
186- engine . CacheBindResult ( signature , rawResult ) ;
170+ engine . CacheBindResult ( signature , result . RawResult ) ;
187171 }
188172
189173 return result ;
190174 }
191175
176+ private MethodBindResult BindMethodInternal ( string name , Type [ ] typeArgs , object [ ] args , object [ ] bindArgs )
177+ {
178+ const CSharpBinderFlags binderFlags = CSharpBinderFlags . InvokeSimpleName | CSharpBinderFlags . ResultDiscarded ;
179+ var binder = Binder . InvokeMember ( binderFlags , name , typeArgs , accessContext ?? engine . AccessContext , CreateArgInfoEnum ( bindArgs ) ) ;
180+
181+ var binding = DynamicHelpers . Bind ( ( DynamicMetaObjectBinder ) binder , target , bindArgs ) ;
182+ var rawResult = ( new MethodBindingVisitor ( target . InvokeTarget , name , binding . Expression ) ) . Result ;
183+ return MethodBindResult . Create ( name , rawResult , target , args ) ;
184+ }
185+
186+ private IEnumerable < string > GetAltMethodNames ( string name )
187+ {
188+ return GetAltMethodNamesInternal ( name ) . Distinct ( ) ;
189+ }
190+
191+ private IEnumerable < string > GetAltMethodNamesInternal ( string name )
192+ {
193+ foreach ( var method in target . Type . GetScriptableMethods ( name , GetMethodBindFlags ( ) ) )
194+ {
195+ var methodName = method . GetShortName ( ) ;
196+ if ( methodName != name )
197+ {
198+ yield return methodName ;
199+ }
200+ }
201+ }
202+
192203 private IEnumerable < CSharpArgumentInfo > CreateArgInfoEnum ( object [ ] args )
193204 {
194205 if ( target is HostType )
@@ -208,14 +219,14 @@ private IEnumerable<CSharpArgumentInfo> CreateArgInfoEnum(object[] args)
208219
209220 private static CSharpArgumentInfo CreateArgInfo ( object arg )
210221 {
211- var flags = CSharpArgumentInfoFlags . None ;
222+ var flags = CSharpArgumentInfoFlags . UseCompileTimeType ;
212223 if ( arg is IOutArg )
213224 {
214- flags |= CSharpArgumentInfoFlags . IsOut | CSharpArgumentInfoFlags . UseCompileTimeType ;
225+ flags |= CSharpArgumentInfoFlags . IsOut ;
215226 }
216227 else if ( arg is IRefArg )
217228 {
218- flags |= CSharpArgumentInfoFlags . IsRef | CSharpArgumentInfoFlags . UseCompileTimeType ;
229+ flags |= CSharpArgumentInfoFlags . IsRef ;
219230 }
220231
221232 return CSharpArgumentInfo . Create ( flags , null ) ;
@@ -228,23 +239,6 @@ private static CSharpArgumentInfo CreateStaticTypeArgInfo()
228239
229240 #endregion
230241
231- #region Nested type: MethodBindEntry
232-
233- private struct MethodBindEntry
234- {
235- public readonly string Name ;
236-
237- public readonly Type AccessContext ;
238-
239- public MethodBindEntry ( string name , Type accessContext )
240- {
241- Name = name ;
242- AccessContext = accessContext ;
243- }
244- }
245-
246- #endregion
247-
248242 #region Nested type: MethodBindResult
249243
250244 private abstract class MethodBindResult
@@ -265,6 +259,12 @@ public static MethodBindResult Create(string name, object rawResult, HostTarget
265259 return new MethodBindFailure ( ( rawResult as Exception ) ?? new NotSupportedException ( MiscHelpers . FormatInvariant ( "Invocation of method '{0}' failed (unrecognized binding)" , name ) ) ) ;
266260 }
267261
262+ public abstract object RawResult { get ; }
263+
264+ public abstract bool IsPreferredMethod ( string name ) ;
265+
266+ public abstract bool IsUnblockedMethod ( ) ;
267+
268268 public abstract object Invoke ( ScriptEngine engine ) ;
269269 }
270270
@@ -289,6 +289,21 @@ public MethodBindSuccess(HostTarget hostTarget, MethodInfo method, object[] args
289289
290290 #region MethodBindResult overrides
291291
292+ public override object RawResult
293+ {
294+ get { return method ; }
295+ }
296+
297+ public override bool IsPreferredMethod ( string name )
298+ {
299+ return ! method . IsBlockedFromScript ( ) && ( method . GetScriptName ( ) == name ) ;
300+ }
301+
302+ public override bool IsUnblockedMethod ( )
303+ {
304+ return ! method . IsBlockedFromScript ( ) ;
305+ }
306+
292307 public override object Invoke ( ScriptEngine engine )
293308 {
294309 if ( method == getTypeMethod )
@@ -317,6 +332,20 @@ public MethodBindFailure(Exception exception)
317332
318333 #region MethodBindResult overrides
319334
335+ public override object RawResult
336+ {
337+ get { return exception ; }
338+ }
339+
340+ public override bool IsPreferredMethod ( string name )
341+ {
342+ return false ;
343+ }
344+
345+ public override bool IsUnblockedMethod ( )
346+ {
347+ return false ;
348+ }
320349 public override object Invoke ( ScriptEngine engine )
321350 {
322351 throw exception ;
0 commit comments