2013-02-06 24 views
0

我在看問題Use 'dynamic' throw a RuntimeBinderException。我面臨着類似的問題:爲什麼我必須手動創建ExpandoObject才能正確使用動態關鍵字?

基本上,我想創建ASP.NET MVC一個「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變量時,它顯然確實有一個Position屬性。

調用者和被調用者位於單獨的程序集中。爲什麼會發生這個問題?

(該解決方案已被證明在同樣的問題:Manually create an ExpandoObject持有參數)

實現:

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()); 
    } 
} 

[編輯,以更清楚的是出現我的問題時,「明顯「位置屬性已設置。我知道,如果財產從來沒有被定義在首位,必須提出例外。]

回答

3

該代碼是致命的缺陷。

確實工作,只要你指定屬性:

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可以使您的API跨裝配邊界使用。

那麼它是如何工作的?

就像在鏈接的答案,你需要手動創建的屬性的字典。無論是使用普通的舊Dictionary<string, object>ExpandoObject是偏好的問題。
使用ExpandoObject將會使你的代碼簡單一點讀取和寫入,但它不是必需的。


關於實際的異常給你:
請注意,它會告訴你它找不到objectPosition財產。如果它是一個匿名類型,但是缺少Position屬性,則異常消息不會引用object,而是指匿名類型。事情是這樣的:

'<>f__AnonymousType0'不包含定義「位置」

+0

是的,我知道了「當前位置」屬性必須存在。正如所說的那樣,只要具有args,它就「確實存在」。觀察窗口中的ToString()向我顯示「Position = 4,Size = 6」,但代碼仍然拋出異常。 – Cornelius

+0

@ClearsTheScreen:它不應該那樣做,它當然不會爲我做。請嘗試我發佈的代碼 - 是否拋出?如果沒有,請嘗試通過將其更改爲代碼來進行修改 - 一次更改一次。 –

+0

我以爲我那樣做了,但我顯然不應該在晚上調試。謝謝你在右側的微調。 +1 :) – Cornelius

相關問題