字典,其中值是 C# 中的匿名类型

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1619518/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-06 19:27:01  来源:igfitidea点击:

A dictionary where value is an anonymous type in C#

c#.netlinqdictionaryanonymous-types

提问by abatishchev

Is it possible in C# to create a System.Collections.Generic.Dictionary<TKey, TValue>where TKeyis unconditioned class and TValue- an anonymous class with a number of properties, for example - database column name and it's localized name.

是否可以在 C# 中创建一个System.Collections.Generic.Dictionary<TKey, TValue>where TKeyis unconditional 类和TValue- 一个具有许多属性的匿名类,例如 - 数据库列名称及其本地化名称。

Something like this:

像这样的东西:

new { ID = 1, Name = new { Column = "Dollar", Localized = "Доллар" } }

采纳答案by itowlson

You can't declare such a dictionary type directly (there are kludges but these are for entertainment and novelty purposes only), but if your data is coming from an IEnumerableor IQueryablesource, you can get one using the LINQ ToDictionary()operator and projecting out the required key and (anonymously typed) value from the sequence elements:

您不能直接声明这样的字典类型(有一些杂项,但这些仅用于娱乐和新颖目的),但是如果您的数据来自IEnumerableorIQueryable来源,则可以使用 LINQToDictionary()运算符并投影出所需的键来获取和(匿名输入的)来自序列元素的值:

var intToAnon = sourceSequence.ToDictionary(
    e => e.Id,
    e => new { e.Column, e.Localized });

回答by Dаn

As itowlsonsaid, you can't declaresuch a beast, but you can indeed createone:

正如itowlson所说,你不能声明这样一个野兽,但你确实可以创造一个:

static IDictionary<TKey, TValue> NewDictionary<TKey, TValue>(TKey key, TValue value)
{
    return new Dictionary<TKey, TValue>();
}

static void Main(string[] args)
{
    var dict = NewDictionary(new {ID = 1}, new { Column = "Dollar", Localized = "Доллар" });
}

It's not clear why you'd actually want to usecode like this.

不清楚为什么您实际上想要使用这样的代码。

回答by noneno

You can do a refection

你可以做一个反思

public static class ObjectExtensions
{
    /// <summary>
    /// Turn anonymous object to dictionary
    /// </summary>
    /// <param name="data"></param>
    /// <returns></returns>
    public static IDictionary<string, object> ToDictionary(this object data)
    {
        var attr = BindingFlags.Public | BindingFlags.Instance;
        var dict = new Dictionary<string, object>();
        foreach (var property in data.GetType().GetProperties(attr))
        {
            if (property.CanRead)
            {
                dict.Add(property.Name, property.GetValue(data, null));
            }
        }
        return dict;
    }
}

回答by jpbochi

I think ASP.NET MVC didn't exit at the time this question was made. It does convert anonymous objects to dictionaries internally.

我认为 ASP.NET MVC 在提出这个问题时没有退出。它确实在内部将匿名对象转换为字典。

Just take a look at the HtmlHelperclass, for example. The method that translates objects to dictionaries is the AnonymousObjectToHtmlAttributes. It it's specifc to MVC and returns an RouteValueDictionary, however.

例如,只需看看HtmlHelperclass。将对象转换为字典的方法是AnonymousObjectToHtmlAttributes. 但是,它特定于 MVC 并返回一个RouteValueDictionary

If you want something more generic, try this:

如果你想要更通用的东西,试试这个:

public static IDictionary<string,object> AnonymousObjectToDictionary(object obj)
{
    return TypeDescriptor.GetProperties(obj)
        .OfType<PropertyDescriptor>()
        .ToDictionary(
            prop => prop.Name,
            prop => prop.GetValue(obj)
        );
}

One intersting advatages of this implementation is that it returns an empty dictionary for nullobjects.

这个实现的一个有趣的优点是它返回一个空的null对象字典。

And here's one generic version:

这是一个通用版本:

public static IDictionary<string,T> AnonymousObjectToDictionary<T>(
    object obj, Func<object,T> valueSelect
)
{
    return TypeDescriptor.GetProperties(obj)
        .OfType<PropertyDescriptor>()
        .ToDictionary<PropertyDescriptor,string,T>(
            prop => prop.Name,
            prop => valueSelect(prop.GetValue(obj))
        );
}

回答by Kevek

If you would like to initialize an empty dictionary you could do something like the this:

如果您想初始化一个空字典,您可以执行以下操作:

var emptyDict = Enumerable
    .Empty<(int, string)>()
    .ToDictionary(
         x => new { Id = x.Item1 }, 
         x => new { Column = x.Item2, Localized = x.Item2});

Basically you just need an empty enumerable with a tuple that has the types you want to use in your final anonymous types and then you can get an empty dictionary that is typed the way you'd like.

基本上,您只需要一个带有元组的空枚举,该元组具有您想要在最终匿名类型中使用的类型,然后您可以获得一个以您喜欢的方式键入的空字典。

If you wanted to you could name the types in the tuple as well:

如果您愿意,也可以命名元组中的类型:

var emptyDict = Enumerable
            .Empty<(int anInt, string aString)>()
            .ToDictionary(
                x => new { Id = x.anInt },
                x => new { Column = x.aString, Localized = x.aString});