我正在尝试不重复代码,所以我有一个方法可以快速转换接口的属性。
我有3个使用此接口的具体类,我希望它们都可以使用此方法。
当我从Session中获取其中一个对象时出现问题。我认为没有办法正确地施放它。
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 :(得分:5)
你需要用括号括起你的演员:
details = ((IHeader<IDetail>)Session["SelectedHeader"]).Details;
答案 1 :(得分:2)
如果您使用的是.NET 4.0,只需使用dynamic
关键字进行投射,以确保正确的自动类型解析:
// note intellisense won't work when you use dynamic keyword...
var details = ((dynamic)Session["SelectedHeader"]).Details;
答案 2 :(得分:2)
好像你刚刚遇到了共同和逆变的奇妙世界。我写了a blog post about it,试图尽可能简单地解释它。
结论:在.NET 4.0之前,您无法将IHeader<ConcreteDetail>
强制转换为IHeader<IDetail>
。
从.NET 4.0开始,您可以使用in
和out
关键字来实现此目的。您可以将界面定义为interface IHeader<out T>
。
如果您还没有使用.NET 4.0,可以通过创建一个新的lambda来解决这个问题:
details = () => Session["SelectedHeader"].Details;