繁体   English   中英

将单方法到多字符串字典映射到单方法到多字符串字典

[英]Mapping a single-method-to-multiple-strings Dictionary to a single-string-to-multiple-method Dictionary

我敢说这是我想出的最复杂的标题。 除了这个示例,我不确定如何更好地解释它:

我有类型。 在这种类型下,我有各种方法,其中有些方法具有一个或多个“ OnAttribute”属性,每个属性定义此方法需要触发的事件名称。 我目前正在通过此查询将“方法字典”添加到事件名称的相关列表中:

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>>>

我需要这个:

[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"]

而是映射到此:

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

我敢肯定,那里有一些更好的术语来描述这一点。 我只是不知道那是什么。

我尝试使用foreach循环以丑陋的方式创建字典,但是正如我所说的那样,这确实很丑陋。 我还尝试将SelectMany()与一些匿名类型一起使用,以将Dictionary展平为一个列表,然后使用GroupBy将列表重新分组为所需的字典,但效率低下且混乱。 我想知道(最佳)LINQ方式。

我希望至少有一点道理。

谢谢你的帮助!

您必须结合使用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

要从当前方法字典中获得反向映射,可以执行以下操作:

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM