![](/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.