2012-03-22 50 views
2

我試圖不重複代碼,所以我有一個方法可以快速轉換接口的屬性。我可以將未知對象轉換爲接口,以便我可以在C#中訪問其屬性?

我有3個具體的類使用這個接口,我希望他們都能夠使用這種方法。

當我從會話中獲得其中一個對象時,就會出現問題。我沒有看到任何方法可以正確投射。

public ActionResult GetItems() 
{ 
    details = (IHeader<IDetail>)Session["SelectedHeader"].Details // Throws invalid cast 
    return Json(details); 
} 

// My interface and class examples: 
interface IHeader<T> where T: IDetail 
{ 
    IList<T> Details { get; set; } 
} 

class ConcreteHeader : IHeader<ConcreteDetail> 
{ 
    public IList<ConcreteDetail> Items { get; set; } 
} 

class ConcreteDetail : IDetail 
{ 
    ... 
} 

,因爲這是在ASP.NET MVC 3的操作方法(除非有一招給)我不能使用泛型。這是可能的,還是我必須爲每個班級編寫一個方法?

編輯:不知道這是從原來的問題清楚:

什麼進入會議是具體對象中的任何一個:

Session["SelectedHeader"] = new ConcreteHeader() { Details = new List<ConcreteDetail>() }; 
+0

你'ConcreteHeader'不但是實現'IDetail',你有'T:IDetail'的通用約束。這甚至是如何編譯的? – 2012-03-22 14:05:13

+0

@ m-y,不應該'ConcreteDetail'實現'IDetail'? – 2012-03-22 14:08:02

+0

@Saeb是的,它的確如此。我可以澄清一下。 – IronicMuffin 2012-03-22 14:11:27

回答

2

如果您使用.NET 4.0,只需使用dynamic關鍵字進行投射,以確保正確的自動類型res解決方案:

// note intellisense won't work when you use dynamic keyword... 
var details = ((dynamic)Session["SelectedHeader"]).Details; 
+0

downvoters:謹慎解釋爲什麼? – code4life 2012-03-22 16:44:57

+0

因爲你的回答是錯誤的。 _「所以IHeader 對象應該堅持沒有問題」_ [見我的回答](http://stackoverflow.com/a/9824219/590790)。 – 2012-03-22 17:29:06

+0

謝謝。我已經刪除了那條評論... – code4life 2012-03-22 17:47:47

5

你需要用括號來包裝你的施法:

details = ((IHeader<IDetail>)Session["SelectedHeader"]).Details; 
+0

雖然你對錯位的parens正確,但它仍然會拋出一個轉換異常:'無法投射'Session [「SelectedHeader」]'(其實際類型爲'ConcreteHeader')爲'IHeader ' – IronicMuffin 2012-03-22 14:23:23

+0

嘗試使用out關鍵字'IHeader '。 – jrummell 2012-03-22 14:25:42

+0

我試過了,看到@Steven Jeuris回答評論 – IronicMuffin 2012-03-22 14:31:35

2

好像你剛纔遇到了共同和反變化的奇妙世界。我寫了a blog post about it,試圖儘可能簡單地解釋它。底線:在.NET 4.0之前,您不能投IHeader<ConcreteDetail>IHeader<IDetail>

從.NET 4.0開始,您可以使用inout關鍵字來允許這樣做。您可以將您的界面定義爲interface IHeader<out T>

如果你不通過創建一個新的拉姆達使用.NET 4.0中,則可以解決這一問題:

details =() => Session["SelectedHeader"].Details;

+0

我已經嘗試過,以前運氣不大。我現在添加了它,並得到以下結果:'無效的方差:類型參數'T'必須在'IHeader .Details'上始終有效。 'T'是covariant.'我想知道是否因爲IList '不支持差異? – IronicMuffin 2012-03-22 14:29:33

+0

Lambda沒有鑄造? – IronicMuffin 2012-03-22 14:32:31

+0

@IronicMuffin那麼,你的差異當然還是需要有效的。這就是爲什麼我說這是一種可能性,而不是保證。 ; p我不是100%確定的,因爲我現在沒有時間仔細研究它,但可能'IList <>'是問題。爲了使用'out',_「類型從類中返回(例如返回值)類型應該是相同的類型,這意味着它也是該類型的任何基類型。該類型只能**用作'輸出'。更詳細的內容在我寫的博客文章中,當然也在msdn文檔中。 – 2012-03-22 14:33:43

相關問題