Возвращая класс, который реализует интерфейс варианта - PullRequest
0 голосов
/ 25 июля 2011

Справочная информация:

У меня есть три страницы Silverlight, которые реализуют мой интерфейс:

interface IPageWithData<in T> where T : Entity
{
    void SetData(T obj);
}

public class APage : Page, IPageWithData<AItem> { /* Implementation */ }
public class BPage : Page, IPageWithData<BItem> { /* Implementation */ }
public class CPage : Page, IPageWithData<CItem> { /* Implementation */ }

// AItem, BItem and CItem are (EF) Entities (they are derived from Entity class).

Затем я использую собственный менеджер, который возвращает страницу, которая относится к узлу древовидной структуры, заданному в качестве параметра:

private static class PageContainerHelper
{
    public static IPageWithData<Entity> SetPage(RadTreeViewItem selectedNode)
    {
        APageRTVI aNode = selectedNode as APageRTVI;
        BPageRTVI bNode = selectedNode as BPageRTVI;
        CPageRTVI cNode = selectedNode as CPageRTVI;

        if (aNode != null)
        {
            if (APage == null)
                APage = new APage();

            APage.SetData(aNode.aItem);
            return APage; // ERROR HERE
        }

        /*
            ... the same for BPageRTVI and CPageRTVI
        */
    }

    public static APage APage { get; set; }
    public static BPage BPage { get; set; }
    public static CPage CPage { get; set; }
}

Проблема:

Кажется, я неправильно понимаю со / контрвариантность. Метод SetPage() не позволяет мне вернуть APage:

Невозможно неявно преобразовать тип 'MyProject.Views.Pages.APage' в 'MyProject.Views.Pages.IPageWithData' . Существует явное преобразование (вам не хватает приведения?)

APage реализует IPageWithData<T> (хотя T имеет более производный тип). Почему это требует явного преобразования? И будет ли здесь работать явное преобразование?

Так что, в принципе, мне нужны две вещи. Во-первых, когда SetPage возвращает страницу, он может использовать страницу, которая реализует IPageWithData типа, который является более производным, чем Entity. И еще мне нужно, чтобы метод IPageWithData<T>.SetData мог получать аргументы более производного типа, чем T, то есть Entity.

Возможно ли это?

1 Ответ

0 голосов
/ 25 июля 2011

Подумайте, что вы можете сделать с IPageWithData<Entity>. Вы можете сделать:

IPageWithData<Entity> pageWithData = PageContainerHelper.SetPage(...);
BItem item = new BItem();
pageWithData.SetData(item);

Теперь реализация - это APage - что бы вы хотели, чтобы она могла делать с BItem? Я подозреваю, что вы этого не хотите.

Другими словами, компилятор делает именно то, что должен - он защищает вас от отправки неверных данных на страницу, которая не может их обработать. Как вы хотите исправить это, я действительно не знаю - я подозреваю, что вы хотите, чтобы SetPage также был универсальным:

public static IPageWithData<T> SetPage<T>(RadTreeViewItem selectedNode)
    where T : Entity

но мне не ясно, что это делает с вашей реализацией.

...