简体   繁体   中英

Overriding a method returning a generic class

in my Silverlight 4 application I started creating and using some generics and now I stumbled upon the following problem:

In a non-generic class, I have a abstract method, that returns a generic class:

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

The generic class is defined in the following way:

public abstract class ServiceModelBase<RootNodeType> where RootNodeType : ServiceNodeBase

Naturally, from DTO_Base derived classes will have to override the CreateBusinessObject method:

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;
  }
}

The line return target; causes an error, stating that it isn't possible to implicitly convert the type ServiceModelEditor in ServiceModelBase<ServiceNodeBase> . Also, an explicit conversion via target as ServiceModelBase<ServiceNodeBase> doesn't work.

How would I have to implement this method to work?

As it is, you've got to return a ServiceModelBase<ServiceNodeBase> . One option is to make your base class generic:

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

Then:

public class DtoEditor : DtoBase<ServiceNodeBase>
{
    public override ServiceModelBase<ServiceNodeBase> CreateBusinessObject()
    {
        ...
    }
}

Try this:

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;

    }
}

I have faced a similar problem before and the only thing reasonable to do is to make the core base class generic also. You can remove the Model generic parameter (and the interface) and it will look a little less scary, but you loose visibility on the functionality of ServiceModelEditor outside of the method.

If you are using .Net 4.0 I suggest you use interfaces to define your ServiceModelBase and specify an out variance modifier on that interface generic type:

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();
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM