C# 使用LINQ将复杂对象映射到字典

C# 使用LINQ将复杂对象映射到字典,c#,linq,dictionary,C#,Linq,Dictionary,考虑以下对象: Controller controller = new Controller() { Name = "Test", Actions = new Action[] { new Action() { Name = "Action1", HttpCache = 300 }, new Action() { Name = "Action2", HttpCache = 200 }, new Action() { Name

考虑以下对象:

Controller controller = new Controller()
{
    Name = "Test",
    Actions = new Action[]
    {
        new Action() { Name = "Action1", HttpCache = 300 },
        new Action() { Name = "Action2", HttpCache = 200 },
        new Action() { Name = "Action3", HttpCache = 400 }
    }
};
如何将此对象映射到以下形式的词典

#key# -> #value#
"Test.Action1" -> 300
"Test.Action2" -> 200
"Test.Action3" -> 400
也就是说,一本
字典

我对LINQ解决方案感兴趣,但我无法解决它


我正在尝试将每个操作映射到KeyValuePair,但我不知道如何获取每个操作的父控制器的Name属性。

主要问题是控制器仍在lambda的作用域中:

var result = controller.Actions.ToDictionary(
  a => string.Format("{0}.{1}", controller.Name, a.Name),
  a => a.HttpCache);

LINQ方法是使用
Select
方法将操作列表投影到字典中。由于您在
控制器
实例上调用它,因此您还可以访问控制器的
名称

myController.Actions.ToDictionary(
    /* Key selector - use the controller instance + action */
    action => myController.Name + "." + action.Name, 
    /* Value selector - just the action */
    action => action.HttpCache);
如果要从多个控制器创建一个大型字典,可以使用
SelectMany
将每个控制器的项投影到控制器+操作列表中,然后将该列表转换为字典:

var namesAndValues = 
    controllers.SelectMany(controller =>
        controller.Actions.Select(action =>
            { 
              Name = controller.Name + "." + action.Name,
              HttpCache = action.HttpCache
            }));
var dict = namesAndValues.ToDictionary(nav => nav.Name, nav => nav.HttpCache); 
您可以尝试以下方法:

var dico = controller.Actions
                     .ToDictionary(a => $"{controller.Name}.{a.Name}", 
                                   a => a.HttpCache);

第一个lambda表达式以键为目标,而第二个表达式以字典项的值为目标

假设一个集合中有多个控制器,而不仅仅是示例代码中的一个
controller
变量,并且希望将它们的所有操作都放在一个字典中,则可以执行以下操作:

var httpCaches = controllers.SelectMany(controller =>
    controller.Actions.Select(action =>
        new
        {
            Controller = controller,
            Action = action
        })
    )
    .ToDictionary(
        item => item.Controller.Name + "." + item.Action.Name,
        item => item.Action.HttpCache);
var controllers = new[] {
    new Controller()
    {
        Name = "Test1",
        Actions = new Action[] {
            new Action { Name = "Action1", HttpCache = 300 },
            new Action { Name = "Action2", HttpCache = 200 },
            new Action { Name = "Action3", HttpCache = 400 },
        }
    },
    new Controller()
    {
        Name = "Test2",
        Actions = new Action[] {
            new Action { Name = "Action1", HttpCache = 300 },
            new Action { Name = "Action2", HttpCache = 200 },
            new Action { Name = "Action3", HttpCache = 400 },
        }
    },
};
这种情况下,您的数据设置如下:

var httpCaches = controllers.SelectMany(controller =>
    controller.Actions.Select(action =>
        new
        {
            Controller = controller,
            Action = action
        })
    )
    .ToDictionary(
        item => item.Controller.Name + "." + item.Action.Name,
        item => item.Action.HttpCache);
var controllers = new[] {
    new Controller()
    {
        Name = "Test1",
        Actions = new Action[] {
            new Action { Name = "Action1", HttpCache = 300 },
            new Action { Name = "Action2", HttpCache = 200 },
            new Action { Name = "Action3", HttpCache = 400 },
        }
    },
    new Controller()
    {
        Name = "Test2",
        Actions = new Action[] {
            new Action { Name = "Action1", HttpCache = 300 },
            new Action { Name = "Action2", HttpCache = 200 },
            new Action { Name = "Action3", HttpCache = 400 },
        }
    },
};

此处缺少两个名称之间的点:
.ToDictionary(a=>$“{controller.Name}.{a.Name}”,
很好的解决方案,但首先检查列表中的所有操作名称是否唯一:)