![](/img/trans.png)
[英]Why can't I do this: dynamic x = new ExpandoObject { Foo = 12, Bar = "twelve" }
[英]Why do I have to manually create ExpandoObject to properly use the dynamic keyword?
我当时在看使用“动态”抛出RuntimeBinderException的问题 。 我面临类似的问题:
基本上,我想在ASP.NET MVC中创建一个使用HTML动态参数的“ HTML帮助器”,类似于许多现有帮助器的htmlArguments参数(以下更多代码):
public BootstrapCell(Action<string> emitContentAction, dynamic args)
视图:
@using (grid.Cell(ViewContext.Writer.Write, new {Position = 4}))
{
<p>zomg!</p>
}
然而,天真的方法,我得到RuntimeBinderException
扔给我,声称'object' does not contain a definition for 'Position'
,即使调试和悬停在_args变量时,它显然也有一个位置属性。
呼叫者和被呼叫者在单独的程序集中。 为什么会发生这个问题?
(该解决方案已在同一问题中显示: 手动创建一个ExpandoObject来容纳args。)
实现方式:
public class Cell
{
private readonly string _tagName;
private dynamic _args;
private Action<string> EmitContentAction;
public BootstrapCell(Action<string> emitContentAction, dynamic args) : DisposableBaseClass
{
_args = args;
EmitContentAction = emitContentAction;
OnContextEnter();
}
protected void OnContextEnter()
{
var sb = new StringBuilder("<");
sb.Append(_tagName);
if (_args.Position > 0)
{
sb.Append(" class=\"offset");
sb.Append(args.Position);
sb.Append("\"");
}
sb.Append(">");
EmitContentAction(sb.ToString());
}
}
[为了使我的问题更清楚地说明,当“显然”设置Position属性时出现了我的问题。 我知道,如果从未首先定义该属性,则必须引发异常。]
该代码存在致命缺陷。
只要您指定该属性,它就可以工作:
void Bar()
{
Foo(new {Position = 0});
}
void Foo(dynamic args)
{
Console.WriteLine(args.Position);
}
这将输出0
,不会抛出RuntimeBinderException
。
但是,此类代码的目的是使调用者可以仅指定所需的属性,而忽略其余的属性。
您正在尝试通过if(args.Position != null)
检查此遗漏。 但这不起作用,它已经需要Position
存在。
当您查看还支持那些匿名配置对象的ASP.NET路由API时,您会注意到参数的类型是object
而不是dynamic
。
使用object
而不是dynamic
object
将使您的API可以跨程序集边界使用。
那么它是怎样工作的?
就像在链接的答案中一样,您需要手动创建属性的字典。 是否使用普通的旧Dictionary<string, object>
或ExpandoObject
是一个优先事项。
使用ExpandoObject
将使您的代码更易于读写,但这不是必需的。
关于实际得到的异常:
请注意,它告诉您在object
上找不到Position
属性。 如果它是缺少Position
属性的匿名类型,则异常消息将不引用object
而是引用匿名类型。 像这样:
'<>f__AnonymousType0'
不包含'Position'的定义
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.