Могу ли я привести неизвестный объект к интерфейсу, чтобы получить доступ к его свойствам в C #? - PullRequest
2 голосов
/ 22 марта 2012

Я пытаюсь не повторять код, поэтому у меня есть метод, который выполняет быстрое преобразование свойства интерфейса.

У меня есть 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>() };

Ответы [ 3 ]

5 голосов
/ 22 марта 2012

Вам нужно заключить в актерский состав скобки:

details = ((IHeader<IDetail>)Session["SelectedHeader"]).Details;
2 голосов
/ 22 марта 2012

Похоже, вы только что столкнулись с чудесным миром со-и контравариантности. Я написал сообщение в блоге об этом , которое пытается объяснить это так просто, как я мог.

Итог: вы не можете разыграть IHeader<ConcreteDetail> до IHeader<IDetail> до .NET 4.0.

Начиная с .NET 4.0, вы можете использовать ключевые слова in и out, чтобы разрешить это. Вы могли бы определить свой интерфейс как interface IHeader<out T>.

Если вы еще не используете .NET 4.0, вы можете обойти эту проблему, создав новую лямбду:

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

2 голосов
/ 22 марта 2012

Если вы используете .NET 4.0, просто приведите с использованием ключевого слова dynamic, чтобы обеспечить правильное разрешение автоматического типа:

// note intellisense won't work when you use dynamic keyword...
var details = ((dynamic)Session["SelectedHeader"]).Details;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...