非泛型工厂方法返回泛型类型

时间:2017-11-09 09:43:16

标签: c# class generics

我在IEnumerable中获得了一些数据对象。数据对象可以是各种类型的。我们打电话给他们:

IEnumerable<BaseData>   

BaseData can be:
AData:BaseData 
BData:BaseData

除了可以在BaseData上运行的方法之外,我还需要创建包装类来提供AData和BData特定功能。

我决定通过实现BaseWrapper类来解决这个问题

AWrapper:BaseWrapper and 
BWrapper:BaseWrapper

.....镜像AData,BData和BaseData的结构。

声明BaseWrapper非常简单:

public abstract class BaseWrapper<T> where T:BaseData
{
     protected T inner;
     // Additional methods consuming "inner" as BaseData.
}

public class AWrapper : BaseWrapper<AData>
{
       //Consuming "inner" variable here strongly typed as AData
}

public class BWrapper : BaseWrapper<BData>
{
       //Consuming "inner" variable here strongly typed as BData
}

但是,如何创建静态工厂方法以允许我的库的使用者写这个:

var wrappedEnumerable = EnumerableBaseData.Select(dt =&gt; BaseData.Create(dt));

我原以为我能做到这一点:

public static BaseWrapper Create(BaseData inner)
{
   if (inner is AData adata)
   {
        return new AWrapper(adata);
   }
   if (inner is BData bdata)
   {
        return new BWrapper(bdata);
   }
// And so on....
}

Create方法的返回类型需要通用参数。 该方法的使用者不必指定type参数。 作为BaseWrapper(T)的基类的非泛型BaseWrapper类实际上没有意义,因为它没有访问BaseData对象的功能。

1 个答案:

答案 0 :(得分:0)

以下代码编译:

public class BaseData
{ }

public class AData : BaseData
{ }

public class BData : BaseData
{ }

public abstract class BaseWrapper
{

}
public abstract class BaseWrapper<T> : BaseWrapper where T : BaseData
{
    protected T inner;

    public BaseWrapper(T data)
    {
        inner = data;
    }

    // Additional methods consuming "inner" as BaseData.

    public static BaseWrapper Create(BaseData inner)
    {
       if (inner is AData)
       {
            return new AWrapper((AData)inner);
       }
       if (inner is BData)
       {
            return new BWrapper((BData)inner);
       }
    // And so on....
       return null;
    }
}

public class AWrapper : BaseWrapper<AData>
{
    //Consuming "inner" variable here strongly typed as AData
    public AWrapper(AData data) : base(data)
    {
    }
}

public class BWrapper : BaseWrapper<BData>
{
    //Consuming "inner" variable here strongly typed as BData
    public BWrapper(BData data) : base(data)
    {

    }
}