2016-11-12 8 views
-2

「集計」、「選択」、およびその他のC#リフレクションのようなすべての拡張メソッドを持つ「文字列」タイプのすべてのメソッドを取得するにはどうすればよいですか?そう、タイプ文字列のすべての拡張メソッド

var type = typeof(string).GetMethods(); //i get all methods string type 
//I want get for this type all extensions methods like "Select" "Where" 
//so i get all interfaces 
type.GetInterfaces(); 
//ICompareble 
//ICloneable 
//... 
//IEnumearable, but all this interfaces don't have extensions methods 
//They locate in Enumerable class 
//how i can use string type go to Enumerable class and get all this methods 
//Somthigs like this 
typeof(Enumerable).GetMethods(); //i want get all this methods but using type "string" 
//Aggregate 
//Select 
//where 
+1

あなたの問題に再現可能なコードを投稿して、私たちのマシンでテストできるようにするのは簡単だと思います。 –

+0

this [link] http://stackoverflow.com/questions/299515/reflection- to-identify-extension-methodsメソッドは、最初のパラメータtypeof(string)を使用しているため機能しません。このメソッドは、最初のパラメータgeneric TSourceを持っています。 – itihonov

答えて

1

拡張メソッドもちろん異なるアセンブリで定義することができます:私は、最初の一般的なparametr TSource.Okと列挙クラス内のすべてのこの拡張メソッドは...コード>はそのタイプが最も< IEnumerableインターフェイスを実装して知っているが、最初の質問は、私たちが気にしているアセンブリです。私たちは、それはそこに、次に利用できる拡張メソッドのための実行可能なソースであるとして、現在のアセンブリとそれが参照するすべてを取得する(インスタンスメソッドやプロパティのコンテキスト内)に

var assemblies = GetType().Assembly 
    .GetReferencedAssemblies() 
    .Select(an => Assembly.Load(an)) 
    .Concat(Enumerable.Repeat(GetType().Assembly, 1)); 

から始めましょう。他の用途には、他の出発点があります。

今、私たちは、すべての拡張メソッドを取得する必要があります。今すぐ

var availableExtensionMethods = assemblies 
    // First get all the types 
    .SelectMany(asse => asse.GetExportedTypes()) 
    // Cut out some which cannot be static classes first 
    .Where(t => t.IsAbstract && t.IsSealed && t.GetConstructors().Length == 0) 
    // Get all their methods. 
    .SelectMany(t => t.GetMethods()) 
    // Restrict to just the extension methods 
    .Where(m => m.GetCustomAttributes().Any(ca => ca is System.Runtime.CompilerServices.ExtensionAttribute) 
    // An extension method must have at least one parameter, but we'll rule out being 
    // messed up by some strangely defined method through weird direct use of 
    // the ExtensionAttribute attribute 
    && m.GetParameters().Length != 0) 
    // Get an object with the method and the first parameter we'll use below. 
    .Select(m => new {Method = m, FirstParam = m.GetParameters()[0]}); 

を、基底クラス(SomeMethod(this object arg))上stringの面で直接定義されたもの(SomeMethod(this string arg))は次のようになります。

var stringExtensions = availableExtensionMethods 
    .Where(info => info.FirstParam.ParameterType.IsAssignableFrom(typeof(string))) 
    .Select(info => info.Method); 

上記には(this IEnumerable<char> arg)が含まれます。ジェネリック型の文字列を実装に一般的に定義されて取得する(例えば(this IEnumerable<T> arg)我々が使用します。

var stringGenericInterfaces = typeof(string).GetInterfaces() 
    .Where(i => i.IsGenericType) 
    .Select(i => i.GetGenericTypeDefinition()); 
    var extensionsOnGenericInterfaces = from info in 
     availableExtensionMethods.Where(aem => aem.FirstParam.ParameterType.ContainsGenericParameters) 
     from inter in stringGenericInterfaces 
     where info.FirstParam.ParameterType.GetGenericTypeDefinition().IsAssignableFrom(inter) 
     select info.Method; 

をあなたはその後、Union一緒にこれらの

多くを取得することができ、私はここにかかわらず、制約のチェックを含めていません。文字列の

+0

非常にマッチしてくれてありがとう、それは仕事です。私はあなたの答えを評価することができません。なぜなら、私は評判が悪いからです。それは私の最初の質問であり、私は "-2"を持っています。理由はありません。なぜなら、私は悪い英語があるからです:)) – itihonov

0

拡張メソッドは、mscorlibアセンブリにSystem.Linqの名前空間であり、列挙クラスとIEnumerableインターフェイスに配置されている 次のような方法で、System.Linqの中に拡張メソッドの名前を取得することができます。

//The actual method to find all extension methods in the assembly 
    //that take IEnumerable<TSource> or TSource as parameters. 
    public static IEnumerable<MethodInfo> GetExtensionMethods(Assembly assembly,Type extendedType) 
    { 
     var query = from type in assembly.GetTypes() 
     where type == typeof(Enumerable) 
     from method in type.GetMethods(BindingFlags.Static 
     | BindingFlags.Public | BindingFlags.NonPublic) 
     where method.IsDefined(typeof(ExtensionAttribute), false) 
     where (method.GetParameters()[0].ParameterType.IsGenericType 
     | (method.GetParameters()[0].ParameterType.ContainsGenericParameters) 
     select method; 

     return query; 
    } 

    //Get the assembly System.Linq 
    Assembly thisAssembly = Assembly.GetAssembly(typeof(Enumerable)); 
    foreach (MethodInfo method in GetExtensionMethods(thisAssembly, 
     typeof(string))) 
    { 
     Console.WriteLine(method); 
    } 
関連する問題