如何在ExpandoObject中使用集合初始化程序语法?

edd*_*dwo 15 c# dynamic syntactic-sugar expandoobject object-initializer

我注意到具有必需和方法的新ExpandoObject工具因此应该可以使用集合初始化语法以与向字典添加项目相同的方式向expando对象添加属性.IDictionary<string,object>IEnumerable<KeyValuePair<string, object>>Add(string, object)

Dictionary<string,object> dict = new Dictionary<string,object>() 
{
    { "Hello", "World" }
};

dynamic obj = new ExpandoObject()
{
    { "foo", "hello" },
    { "bar", 42 },
    { "baz", new object() }
};

int value = obj.bar;
Run Code Online (Sandbox Code Playgroud)

但似乎没有办法做到这一点.错误:

'System.Dynamic.ExpandoObject'不包含'添加'的定义

我认为这不起作用,因为接口是明确实现的.但有没有办法解决这个问题?这工作正常,

IDictionary<string, object> exdict = new ExpandoObject() as IDictionary<string, object>();
exdict.Add("foo", "hello");
exdict.Add("bar", 42);
exdict.Add("baz", new object());
Run Code Online (Sandbox Code Playgroud)

但是集合初始化器语法更整洁.

dav*_*ick 6

我以前需要多次使用简单的ExpandoObject初始化程序,并且通常使用以下两种扩展方法来完成初始化语法之类的操作:

public static KeyValuePair<string, object> WithValue(this string key, object value)
{
    return new KeyValuePair<string, object>(key, value);
}

public static ExpandoObject Init(
    this ExpandoObject expando, params KeyValuePair<string, object>[] values)
{
    foreach(KeyValuePair<string, object> kvp in values)
    {
        ((IDictionary<string, Object>)expando)[kvp.Key] = kvp.Value;
    }
    return expando;
}
Run Code Online (Sandbox Code Playgroud)

然后你可以写下面的内容:

dynamic foo = new ExpandoObject().Init(
    "A".WithValue(true),
    "B".WithValue("Bar"));
Run Code Online (Sandbox Code Playgroud)

一般来说,我发现使用扩展方法KeyValuePair<string, object>从字符串键构建实例会派上用场.显然,您可以将名称更改为类似的内容,Is以便"Key".Is("Value")在需要更简洁的语法时编写.


Ali*_*tad 2

首先,你是当之无愧的。已IDictionary<string,object>明确实施。

你甚至不需要铸造。这有效:

IDictionary<string,object> exdict = new ExpandoObject() 
Run Code Online (Sandbox Code Playgroud)

现在集合语法不起作用的原因是因为它是Dictionary<T,T> 构造函数中的实现,而不是接口的一部分,因此它不适用于 Expando。

上面的说法错误。你是对的,它使用了 add 函数:

static void Main(string[] args)
{
Dictionary<string,object> dictionary = new Dictionary<string, object>()
                                                {
                                                    {"Ali", "Ostad"}
                                                };
}
Run Code Online (Sandbox Code Playgroud)

被编译为

.method private hidebysig static void  Main(string[] args) cil managed
{
  .entrypoint
  // Code size       27 (0x1b)
  .maxstack  3
  .locals init ([0] class [mscorlib]System.Collections.Generic.Dictionary`2<string,object> dictionary,
           [1] class [mscorlib]System.Collections.Generic.Dictionary`2<string,object> '<>g__initLocal0')
  IL_0000:  nop
  IL_0001:  newobj     instance void class [mscorlib]System.Collections.Generic.Dictionary`2<string,object>::.ctor()
  IL_0006:  stloc.1
  IL_0007:  ldloc.1
  IL_0008:  ldstr      "Ali"
  IL_000d:  ldstr      "Ostad"
  IL_0012:  callvirt   instance void class [mscorlib]System.Collections.Generic.Dictionary`2<string,object>::Add(!0,
                                                                                                                 !1)
  IL_0017:  nop
  IL_0018:  ldloc.1
  IL_0019:  stloc.0
  IL_001a:  ret
} // end of method Program::Main
Run Code Online (Sandbox Code Playgroud)

更新

主要原因是Add已实现为protected(没有修饰符,变为protected)。

由于在 上Add可见ExpandoObject,因此不能像上面那样调用它。