是否可以在抽象类的工厂方法中重写泛型类型

本文关键字:方法 重写 泛型类型 工厂 抽象类 是否 | 更新日期: 2023-09-27 17:56:56

我有一个工厂类,它返回从抽象类型继承的具体实例。这些具体实例还具有其数据类型的泛型属性,因为每个实例都需要不同的数据类型。Data 属性也存在于抽象类型上,因为它是在工厂中设置的。

public static class FactoryClass 
{
  public static TType CreateNewClass<TType>(object data) 
        where TType : AbstractClass<object>, new()
  {
    var newClass = new TType {Data = data};
    // do some stuff
    // keep track of all created types in a list
    List.Add(newClass);
    return newClass;
  }
  private List<AbstractClass<object>> MyList = new List<AbstractClass<object>>()
}
public abstract class AbstractClass<TData>
{
  internal AbstractClass()
  {
    // do constructor things
  }
  protected SomeCommonFunction()
  {
    // common code for abstract base class
  }
  public abstract void DoSomethingToData();
  TData Data;
}
public class ExampleClass : AbstractClass<string[]>
{
  public override void DoSomethingToData()
  {
    // sort the strings or something
    // call the abstract code
  }
}

当我尝试调用FactoryClass.CreateNewClass<ExampleClass>(myStringArray)时,我收到一个错误,提示它需要可转换AbstractClass<object>

有没有更好的方法来做我想做的事情?

是否可以在抽象类的工厂方法中重写泛型类型

嗯,这就是问题所在:

where TType : AbstractClass<object>

该约束正是编译器抱怨的约束。

在我看来,你真的想要这样的东西:

public static TContainer CreateNewClass<TContainer, TData>(TData data) 
    where TContainer : AbstractClass<TData>, new()

不幸的是,这需要您为该方法指定两个类型参数 - 但至少就您使用的数据类型而言,它是安全的。您可以通过创建两个泛型方法和一个单独的类来解决此问题,以便在它们之间使用,从而允许您编写类似以下内容的内容:

FactoryClass.For(myStringArray).CreateNewClass<ExampleClass>();

For方法将返回一个类型参数为 string[] 的泛型类型,然后CreateNewClass将是一个实例方法,该方法采用数据类型的容器类型。

但是,您的列表根本无法以当前形式工作。您可能希望为 AbstractClass 创建一个非泛型基类:

public abstract class AbstractClass
{
    // Anything which doesn't use TData
}

然后:

public abstract class AbstractClass<TData> : AbstractClass

此时,工厂中的列表将是一个List<AbstractClass>;您不会以编译时安全的方式知道每个条目的数据类型...这是完全有意义的,因为每个元素都可以使用不同的类型。

(哦,当然,如果你想从静态方法访问它,你的列表字段需要是静态的......