2017-05-09 9 views
0

私はこれまでに思い付いた最も複雑なタイトルです。 私はそれをよりよく説明する方法がわかりませんが、この例の短さ:単一のメソッドから複数の文字列への辞書のマッピング単一の文字列から複数のメソッドへの辞書

私はタイプがあります。このタイプでは、さまざまなメソッドが用意されています。これらのメソッドには、OnAttribute属性が1つ以上付けられており、それぞれがこのメソッドが起動する必要のあるイベント名を定義します。私は現在、このクエリでイベント名のその関連リストにメソッドの辞書を取得しています:

var methods = this.GetType().GetMethods() 
    .Where(m => Attribute.IsDefined(m, typeof(OnAttribute))) 
    .ToDictionary(m => m, 
     m => m.GetCustomAttributes(typeof(OnAttribute), true) 
      .Select(a => ((OnAttribute)a).EventName)); //OnAttribute defines an EventName field 

結果の型がIEnumerable<IGrouping<System.Reflection.MethodInfo,IEnumerable<string>>>です。しかし、リクエストされたイベントのメソッドに署名するためには、各イベント名を実行するよう要求するすべてのメソッドに、各イベント名をマップする必要があります。言い換えれば、前述のタイプがIEnumerable<IGrouping<string,IEnumerable<System.Reflection.MethodInfo>>>にマッピングされている必要があります。

私はこの必要があります:私は確信している

"Event_1" => [Method_1,Method_2] 
"Event_2" => [Method_1,Method_3] 
"Event_3" => [Method_2] 
"Event_4" => [Method_1] 

:私の現在のコードを使用して、

[On("Event_1")] 
[On("Event_2")] 
[On("Event_4")] 
void Method_1() 
{ 
    ... 
} 

[On("Event_1")] 
void Method_2() 
{ 
    ... 
} 

[On("Event_2")] 
[On("Event_3")] 
void Method_3() 
{ 
    ... 
} 

、これにマッピングします:

代わりにこれにマッピングされ
Method_1 => ["Event_1","Event_2","Event_4"] 
Method_2 => ["Event_1"] 
Method_3 => ["Event_2","Event_3"] 

をこれを記述するために、そこにいくつかのより良い専門用語があります。私はそれが何であるか分かりません。

私はforeachループを使用して醜い方法で辞書を作成しようとしましたが、私が言ったように、それは実際に uglyです。また、SelectMany()をいくつかの匿名型とともに使用して、辞書をリストにまとめてから、GroupByを使用してそのリストを自分の望む辞書に再グループ化しようとしましたが、それは非効率的で面倒です。私はこれを行う(最高)LINQの方法を知りたいです。

私はそれが少なくともちょっとした感覚で作られたことを願っています。

ありがとうございました!

答えて

2

必要な結果を得るには、SelectManyGroupByの組み合わせを使用する必要があります。ここで

が動作しているようだソリューションです:

var methods = this.GetType().GetMethods() 
    .Where(m => Attribute.IsDefined(m, typeof(OnAttribute))) 
    .SelectMany(m => m.GetCustomAttributes(typeof(OnAttribute), true) 
      .Select(a => new { EventName = ((OnAttribute)a).EventName, MethodInfo = m })) 
    .GroupBy(g => g.EventName, g => g.MethodInfo); 

このソリューションでは、コレクションは、最初EventNameMethodInfoを含む匿名型の中間のコレクションを取得するために平坦化されます。この匿名型の中間コレクションは、EventNameでグループ化され、EventNameによってメソッドのグループを取得します。

+0

私はいくつかのベンチマークを実行し、 'new KeyValuePair(EventName、MethodInfo)'を使うことは、 'new {EventName、MethodInfo}'(匿名のtyペス) –

0

方法のあなたの現在の辞書から逆マッピングを取得するには、あなたがこれを行うことができます:

var reverseMapping = methods 
    .SelectMany(kvp => kvp.Value, (kvp, evt) => new { Event = evt, Method = kvp.Key }) 
    .GroupBy(a => a.Event, a => a.Method); 

次に、あなたがそれらをダンプする場合:

foreach (var grouping in reverseMapping.OrderBy(g => g.Key)) 
{ 
    Console.WriteLine(string.Format("{0} => {1}", 
     grouping.Key, string.Join(",", grouping.Select(m => m.Name)))); 
} 

はフィドル:https://dotnetfiddle.net/SdE7LD

関連する問題