2014-03-01 73 views
1

我想要使用反射返回正確的「Where」擴展方法,以便構建自定義表達式。我嘗試了幾種方法,但最接近我拋出一個異常: 「mscorlib.dll中發生類型'System.Reflection.AmbiguousMatchException'的未處理異常」如何爲「Where」擴展方法獲取正確的MethodInfo

我知道這是因爲有兩個Where方法定義在Enumrable類 - 但我怎麼能返回其只用短短的

Func<T, bool>. 

謂我目前所面對的是Where方法:

var collectionType = typeof(TSub); 
Type tIEnumerable = typeof(IEnumerable<>).MakeGenericType(collectionType); 

MethodInfo methodInfo = 
     typeof(Enumerable) 
     .GetMethod("Where")     
     .MakeGenericMethod(collectionType); 

我自己也嘗試(這一個回報null):

MethodInfo methodWhere = typeof(Enumerable).GetMethod("Where", new[] { typeof(TSub)}); 

和(也返回null)

MethodInfo methodWhere = typeof(Enumerable).GetMethod("Where", new[] { collectionType }) 

和(這個方法返回相同的曖昧除外)

MethodInfo methodWhere = typeof(Enumerable).GetMethod("Where", BindingFlags.Public |  BindingFlags.Static) 

任何人都可以在所有幫助嗎?

感謝

回答

1

在我看來,目前的答案,包括接受一個比必要的要複雜得多。如果你有一個類型T,你可以在編譯時使用,就可以得到MethodInfo像這樣:

Func<IEnumerable<T>, Func<T, bool>, IEnumerable<T>> whereDelegate = Enumerable.Where; 
MethodInfo whereMethodInfo = whereDelegate.Method; 

額外的好處,這是強類型。它將只編譯如果Enumerable.Where可以解決的,而不是任何查找字符串"Where":將編譯就好了,如果你不小心輸入"Wehre"代替,但會在運行時失敗。

+0

非常感謝,我認爲你是對的。這種方式可行,代碼少 - 再次感謝 – user3161050

0

我認爲最簡單的方法來告訴兩個重載除了爲:

var whereMethod = typeof(Enumerable).GetMethods() 
       .Single(m => m.Name == "Where" && m.GetParameters()[1].ParameterType.GetGenericTypeDefinition() == typeof(Func<,>)) 
.MakeGenericType(typeof(TSub)); 
0

具有模板類型T,這應該工作:

var methodWhere = typeof(Enumerable).GetMethod("Where", BindingFlags.Public | BindingFlags.Static, new Type[]{ typeof(IEnumerable<T>), typeof(Func<T, bool>) }); 

Where方法需要兩個參數:IEnumerable和比較函數。

+0

感謝您的想法。以上不編譯(無效參數),所以我嘗試:var methodWhere = typeof(Enumerable).GetMethod(「Where」,new Type [] {typeof(IEnumerable ),typeof(Func )});但不幸的是這返回null。我會看看,如果我現在可以玩弄你的想法,並讓它工作.... – user3161050

1

我敢肯定有更簡單的方法,但這裏有一個:

typeof(Enumerable).GetMethods() 
        .Single(method => method.Name == "Where" 
          && method.GetParameters() 
            .ElementAt(1) 
            .ParameterType 
            .GetGenericTypeDefinition() == typeof(Func<,>)) 
        .MakeGenericMethod(typeof(TSub)) 

這是有點脆,但(認爲微軟在.NET的未來版本中加入更多的過載)。也許更強大的(但更可怕的;當然,必須有一個更好的方法)是:

var methods = from method in typeof(Enumerable).GetMember("Where") 
               .OfType<MethodInfo>()        
       let typeArgs = method.GetGenericArguments() 
       where typeArgs.Length == 1 
       let typeArg = typeArgs.Single() 
       where !typeArg.GetGenericParameterConstraints().Any() 
       let seqtype = typeof(IEnumerable<>).MakeGenericType(typeArg)      
       where method.ReturnType == seqtype 
       let expectedParams = new[] 
       { 
       seqtype, 
       typeof(Func<,>).MakeGenericType(typeArg, typeof(bool)) 
       } 
       where method.GetParameters() 
          .Select(parameter => parameter.ParameterType) 
          .SequenceEqual(expectedParams) 

       select method.MakeGenericMethod(typeof(TSub)); 


var result = methods.Single(); 
+0

This Works,so thanks very much .... now to get this to work in my custom expression! :-) – user3161050

相關問題