【问题标题】:How to turn a list of strings into an anonymous type with a property per character如何将字符串列表转换为每个字符都有一个属性的匿名类型
【发布时间】:2017-07-17 15:39:23
【问题描述】:

假设我有一个List<string>,其中每个字符串的长度相同。这个长度是事先不知道的,只能通过在运行时检查字符串的 Length 属性(比如第一个,因为它们都是相同的长度)来确定。

我希望最终得到一组匿名对象,每个对象都有属性 C1、C2 等,每个字符都有一个。

因此,如果列表中的第一个字符串是“abcd”,那么结果列表中的第一个匿名对象将是...

{
  C1 = "a",
  C2 = "b",
  C3 = "c",
  C4 = "d"
}

这可能吗?我一直在为动力学和 ExpandoObjects 苦苦挣扎,但没有设法让它们中的任何一个工作。主要问题似乎是事先不知道属性名称。

我试着做一些事情,比如(在一个循环中)......

d["C" + i] = str.[j];

...但这不起作用,因为它认为我正在尝试使用数组索引。我得到一个运行时异常“无法使用 [] 将索引应用于 'System.Dynamic.ExpandoObject' 类型的表达式”

这个可以吗?

【问题讨论】:

  • 我想知道您将如何使用这些对象?那么“abba”字符串呢?
  • 消费不是问题,因为这将被传递给 WPF 网格,它将属性绑定到我们动态添加的列。重复的字符也不是问题,因为字符串中字符的顺序很重要。不认为那一点是相关的,所以没有在问题中提及它
  • @AvrohomYisroel:也许您可以看一下TypeBuilder 实用程序:msdn.microsoft.com/en-us/library/… 这样,您可以迭代输入并生成映射属性并分配值。关于 Expando,如果您先将其转换为字典,则可以像索引器一样将属性/数据插入其中:stackoverflow.com/a/26778625/1269654 编辑:对于 expando 来说可能是一个更好的答案:stackoverflow.com/a/10048479/1269654
  • @ChrisSinclair 感谢您的建议。我查看了将ExpandoObject 转换为Dictionary,但问题是我不知道如何处理object,因为我只知道运行时的属性数量。我去看看TypeBuilder
  • @AvrohomYisroel:会不会和你的示例代码很相似? for(int i = 1; i <= myString.Length; i++) ((IDictionary<string, object>)d)["C" + i] = myString[i - 1];

标签: c# dynamic expandoobject


【解决方案1】:

您可以将ExpandoObject 视为一个字典,其中属性名称作为键,值作为属性值。使用这个简单的扩展方法,您可以创建一个 ExpandoObject 并使用从源字符串生成的属性填充它:

public static ExpandoObject ToExpando(this string s)
{
    var obj = new ExpandoObject();
    var dictionary = obj as IDictionary<string, object>;       
    var properties = s.Distinct().Select((ch, i) => new { Name = $"C{i+1}", Value = ch });

    foreach (var property in properties)
        dictionary.Add(property.Name, property.Value);

    return obj;
}

用法:

var source = new List<string> { "bob", "john" };
var result = source.Select(s => s.ToExpando());

输出:

[
  {
    "C1": "b",
    "C2": "o"
    // NOTE: If C3 = "b" is required here, than remove Distinct() in extension method
  },
  {
    "C1": "j",
    "C2": "o",
    "C3": "h",
    "C4": "n"
  }
]

【讨论】:

  • 我认为 Distinct() 可能不是 OP 意图的一部分。正如您所提到的,“abba”可以映射到:C1=a, C2=b, C3=b, C4=a,我认为这不会引起问题。编辑:否则,我认为这可以满足要求。
  • @ChrisSinclair 是的,如果重复值没问题,那么应该在此处删除 Disctinct()。可能我的评论没有得到正确的 OP 答案
  • @SergeyBerezovskiy 我以为我已经回答过了,我说字符的顺序很重要,所以我知道第一个字符代表什么,不在乎它是否恰好相同char 作为一个处于不同位置的字符。无论哪种方式,您的代码看起来都很棒,谢谢。我只是在玩弄它,因为我认为我实际上可以放弃 ExpandoObject 并直接处理 Dictionary&lt;String, dynamic&gt; 类型的对象
  • @SergeyBerezovskiy 正如我所想,这可以简化。您可以创建一个 Dictionary&lt;String, dynamic&gt; 并为其添加属性。根本不需要ExpandoObject。再次感谢
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-09-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-07-05
相关资源
最近更新 更多