所以我使用ExpandoObject添加动态填充到字符串中的属性。我将在稍后使用它们绑定到DataGrid。下面给出了代码的两个变体,看起来它们正在做同样的事情(对我来说至少)但是一个失败而一个没有。有人可以帮我理解为什么会这样吗?
代码失败
dynamic dynamo = new ExpandoObject() as IDictionary<string,object>;
string words[] = basestring.Split('|');
foreach(string word in words)
{
dynamo[word] = word.ToUpperInvariant();
}
成功代码
dynamic dynamo = new ExpandoObject();
var dynamoose = dynamo as as IDictionary<string,object>; //Notice the cast
string words[] = basestring.Split('|');
foreach(string word in words)
{
dynamoose[word] = word.ToUpperInvariant();
}
`
答案 0 :(得分:0)
您的代码不会直接运行。我无法获得双重投射工作。你的字符串单词[]没有编译,所以我把它改成字符串[]字。
从那里开始,失败的代码给了我这个有价值的信息:
其他信息:无法将带有[]的索引应用于表达式 类型&#39; System.Dynamic.ExpandoObject&#39;
你的第二段代码有效,因为你有一个IDictionary实例,而失败的一块试图在动态上调用[] -indexing运算符。
答案 1 :(得分:0)
这不是一个真正的答案,但我试图展示编译器的功能。所以试试一个更简单的程序版本:
private static void Main(string[] args)
{
Method1();
Method2();
}
private static void Method1()
{
var expando = new ExpandoObject() as IDictionary<string, object>;
expando["key"] = 1;
}
private static void Method2()
{
dynamic expando = new ExpandoObject() as IDictionary<string, object>;
expando["key"] = 1;
}
使用ILSpy,您可以看到编译器创建的内容,甚至在使用任何运行时之前:
[CompilerGenerated]
private static class <Method2>o__SiteContainer0
{
public static CallSite<Func<CallSite, object, string, int, object>> <>p__Site1;
}
private static void Main(string[] args)
{
Program.Method1();
Program.Method2();
}
private static void Method1()
{
IDictionary<string, object> expando = new ExpandoObject();
expando["key"] = 1;
}
private static void Method2()
{
object expando = new ExpandoObject();
if (Program.<Method2>o__SiteContainer0.<>p__Site1 == null)
{
Program.<Method2>o__SiteContainer0.<>p__Site1 = CallSite<Func<CallSite, object, string, int, object>>.Create(Binder.SetIndex(CSharpBinderFlags.None, typeof(Program), new CSharpArgumentInfo[]
{
CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null),
CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.UseCompileTimeType | CSharpArgumentInfoFlags.Constant, null),
CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.UseCompileTimeType | CSharpArgumentInfoFlags.Constant, null)
}));
}
Program.<Method2>o__SiteContainer0.<>p__Site1.Target(Program.<Method2>o__SiteContainer0.<>p__Site1, expando, "key", 1);
}
Method1应该非常清楚,因为编译器只将var更改为IDictionary并按预期使用expando。
在Method2中,编译器执行&#34; magic&#34;。如this answer中所述,IDictionary是一个显式接口,无法通过类实例访问。
如果将动态转换为IDictionary,编译器会创建一个非常不同的代码:
private static void Method3()
{
dynamic expando = new ExpandoObject();
((IDictionary<string, object>)expando)["key"] = 1;
}
将成为
[CompilerGenerated]
private static class <Method3>o__SiteContainer0
{
public static CallSite<Func<CallSite, object, IDictionary<string, object>>> <>p__Site1;
}
private static void Method3()
{
object expando = new ExpandoObject();
if (Program.<Method3>o__SiteContainer0.<>p__Site1 == null)
{
Program.<Method3>o__SiteContainer0.<>p__Site1 = CallSite<Func<CallSite, object, IDictionary<string, object>>>.Create(Binder.Convert(CSharpBinderFlags.ConvertExplicit, typeof(IDictionary<string, object>), typeof(Program)));
}
Program.<Method3>o__SiteContainer0.<>p__Site1.Target(Program.<Method3>o__SiteContainer0.<>p__Site1, expando)["key"] = 1;
}
如您所见,CallSite现在使用IDictionary类型。