C# 为什么我必须手动创建ExpandooObject才能正确使用dynamic关键字?
我在看这个问题。我面临着一个类似的问题: 基本上,我想在ASP.NET MVC中创建一个使用动态参数的“HTML帮助程序”,类似于许多现有帮助程序的htmlArguments参数(下面有更多代码):C# 为什么我必须手动创建ExpandooObject才能正确使用dynamic关键字?,c#,dynamic,expandoobject,C#,Dynamic,Expandoobject,我在看这个问题。我面临着一个类似的问题: 基本上,我想在ASP.NET MVC中创建一个使用动态参数的“HTML帮助程序”,类似于许多现有帮助程序的htmlArguments参数(下面有更多代码): public BootstrapCell(操作emitContentAction,动态参数) 视图: @使用(grid.Cell(ViewContext.Writer.Write,new{Position=4})) { 僵尸 } 然而,在这种幼稚的方法中,我得到了抛出的RuntimeBinder
public BootstrapCell(操作emitContentAction,动态参数)
视图:
@使用(grid.Cell(ViewContext.Writer.Write,new{Position=4}))
{
僵尸
}
然而,在这种幼稚的方法中,我得到了抛出的RuntimeBinderException
,声明'object'不包含“Position”的定义
,即使在调试和悬停在_args变量上时,它显然有Position属性
调用者和被调用者位于不同的程序集中。为什么会出现这样的问题
(解决方案已在同一个问题中显示:保留args。)
实施:
公共类单元格
{
私有只读字符串\u标记名;
私有动态参数;
私人诉讼;
public BootstrapCell(Action emitContentAction,dynamic args):DisposableBaseClass
{
_args=args;
EmitContentAction=EmitContentAction;
OnContexter();
}
受保护的void onContexter()
{
var sb=新的StringBuilder(“”);
(某人的)行动;
}
}
[经过编辑,以更清楚地说明当“显然”设置Position属性时会出现我的问题。我知道,如果该属性从一开始就没有定义,则必须引发异常。]该代码存在致命缺陷 只要指定该属性,它就可以工作:
void Bar()
{
Foo(new {Position = 0});
}
void Foo(dynamic args)
{
Console.WriteLine(args.Position);
}
这将输出0
,它不会抛出RuntimeBinderException
但是这种代码的目的是调用方可以只指定所需的属性,而忽略其余的属性。您正试图通过
if(args.Position!=null)
检查此遗漏。但这不起作用,它已经需要位置
存在
当您查看同样支持这些匿名配置对象的ASP.NET路由API时,您会注意到参数的类型是object
,而不是dynamic
使用
对象
而不是动态
将使API能够跨程序集边界使用
那么它是如何工作的呢?
就像在链接答案中一样,您需要手动创建属性字典。您是使用普通的字典
还是使用扩展对象
,这取决于您的偏好。使用
ExpandoObject
将使代码的读写更加简单,但这不是必需的
关于您得到的实际异常:
请注意,它告诉您在
对象
上找不到位置
属性。如果是缺少位置
属性的匿名类型,则异常消息不会引用对象
,而是引用匿名类型。大概是这样的:
“f\uu AnonymousType0”
不包含“位置”的定义
该代码存在致命缺陷 只要指定该属性,它就可以工作:
void Bar()
{
Foo(new {Position = 0});
}
void Foo(dynamic args)
{
Console.WriteLine(args.Position);
}
这将输出0
,它不会抛出RuntimeBinderException
但是这种代码的目的是调用方可以只指定所需的属性,而忽略其余的属性。您正试图通过
if(args.Position!=null)
检查此遗漏。但这不起作用,它已经需要位置
存在
当您查看同样支持这些匿名配置对象的ASP.NET路由API时,您会注意到参数的类型是object
,而不是dynamic
使用
对象
而不是动态
将使API能够跨程序集边界使用
那么它是如何工作的呢?
就像在链接答案中一样,您需要手动创建属性字典。您是使用普通的字典
还是使用扩展对象
,这取决于您的偏好。使用
ExpandoObject
将使代码的读写更加简单,但这不是必需的
关于您得到的实际异常:
请注意,它告诉您在
对象
上找不到位置
属性。如果是缺少位置
属性的匿名类型,则异常消息不会引用对象
,而是引用匿名类型。大概是这样的:
“f\uu AnonymousType0”
不包含“位置”的定义
是的,我知道“position”属性必须存在。如前所述,它“确实存在”,因为在watch窗口中有args.ToString()向我显示“位置=4,大小=6”,但代码仍然抛出异常。@清除屏幕:它不应该这样做,它当然不适合我。请尝试我发布的代码-它会抛出吗?如果没有,试着把它改成你的代码——一次一个修改。我想我就是这么做的,但是我显然不应该在晚上调试。谢谢你在正确的方向推动+1:)@ClearsTheScreen:BTW:您的异常告诉我您在此处显示的代码不是引发异常的代码。调用必须如下所示才能产生异常:
grid.Cell(ViewContext.Writer.Write,new object())
。我这么说是因为异常不会指向对象
,而是指向一个匿名类型:'f_uanonymoustype0'不包含“Position”的定义
我的问题很简单,我在ass中使用了动态
对象