Переопределение метода, возвращающего универсальный класс - PullRequest
0 голосов
/ 30 ноября 2011

в своем приложении Silverlight 4 я начал создавать и использовать некоторые шаблоны и теперь наткнулся на следующую проблему:

В неуниверсальном классе у меня есть абстрактный метод, который возвращает универсальный класс:

public abstract class DTO_Base()
{
  public abstract ServiceModelBase<ServiceNodeBase> CreateBusinessObject();
}

Общий класс определяется следующим образом:

public abstract class ServiceModelBase<RootNodeType> where RootNodeType : ServiceNodeBase

Естественно, из производных классов DTO_Base придется переопределить метод CreateBusinessObject:

public class DTO_Editor : DTO_Base
{
  public override ServiceModelBase<ServiceNodeBase> CreateBusinessObject()
  {
    // the object to return have to be of type ServiceModelEditor
    // which is derived from ServiceModelBase<ServiceNodeEditor>
    // public class ServiceModelEditor : ServiceModelBase<ServiceNodeEditor>

    // ServiceNodeEditor is derived from ServiceNodeBase
    // public class ServiceNodeEditor : ServiceNodeBase
    ServiceModelEditor target = new ServiceModelEditor()

    ...
    Functions to populate the 'target'
    ...

    return target;
  }
}

Строка return target; вызывает ошибку, утверждая, что невозможно неявно преобразовать тип ServiceModelEditor в ServiceModelBase<ServiceNodeBase>. Кроме того, явное преобразование через цель как ServiceModelBase<ServiceNodeBase> не работает.

Как мне реализовать этот метод для работы?

Ответы [ 3 ]

1 голос
/ 30 ноября 2011

Попробуйте:

public interface IDTO<Node> where Node : ServiceNodeBase
{
    ServiceModelBase<Node> CreateBusinessObject();
}
public abstract class DTO_Base<Model,Node> : IDTO<Node>
    where Model : ServiceModelBase<Node>
    where Node : ServiceNodeBase
{
    public abstract Model CreateBusinessObject();


    #region IDTO<Node> Members

    ServiceModelBase<Node> IDTO<Node>.CreateBusinessObject()
    {
        return CreateBusinessObject();
    }

    #endregion
}

public class DTO_Editor : DTO_Base<ServiceModelEditor, ServiceNodeEditor>
{

    public override ServiceModelEditor CreateBusinessObject()
    {
        // the object to return have to be of type ServiceModelEditor
        // which is derived from ServiceModelBase<ServiceNodeEditor>
        // public class ServiceModelEditor : ServiceModelBase<ServiceNodeEditor>

        // ServiceNodeEditor is derived from ServiceNodeBase
        // public class ServiceNodeEditor : ServiceNodeBase
        ServiceModelEditor target = new ServiceModelEditor();


        return target;

    }
}

Ранее я сталкивался с подобной проблемой, и единственное, что разумно сделать, это сделать базовый базовый класс также универсальным.Вы можете удалить универсальный параметр Model (и интерфейс), и он будет выглядеть немного менее пугающим, но вы потеряете представление о функциональности ServiceModelEditor вне метода.

1 голос
/ 30 ноября 2011

На самом деле, вы получили , чтобы вернуть ServiceModelBase<ServiceNodeBase>. Один из вариантов - сделать базовый класс общим:

public abstract class DtoBase<T> where T : RootNodeType
{
    public abstract ServiceModelBase<T> CreateBusinessObject();
}

Тогда:

public class DtoEditor : DtoBase<ServiceNodeBase>
{
    public override ServiceModelBase<ServiceNodeBase> CreateBusinessObject()
    {
        ...
    }
}
0 голосов
/ 30 ноября 2011

Если вы используете .Net 4.0, я предлагаю вам использовать интерфейсы для определения ServiceModelBase и указать модификатор out для этого универсального типа интерфейса:

class ServiceNodeBase { }
class ServiceNodeEditor : ServiceNodeBase {/*implementation*/}
//
interface IServiceModelBase<out RootNodeType>
    where RootNodeType : ServiceNodeBase { 
}
class ServiceModelEditor : IServiceModelBase<ServiceNodeEditor> {
    /*implementation*/
}
//
abstract class DTO_Base {
    public abstract IServiceModelBase<ServiceNodeBase> CreateBusinessObject();
}
class DTO_Editor : DTO_Base {
    public override IServiceModelBase<ServiceNodeBase> CreateBusinessObject() {
        return new ServiceModelEditor();
    }
}
...