【问题标题】:How do I actually use a generic type in my generic service to create new objects?如何在我的泛型服务中实际使用泛型类型来创建新对象?
【发布时间】:2017-03-27 22:45:54
【问题描述】:

注意:为了写出一个相当简短的问题,我创建了一个类似于我的应用程序的问题区域的示例。实际例子比较复杂,但问题陈述是准确的。

假设我有一个抽象基类:

public abstract class AnalysisObject
{
    public virtual AnalysisObject CreateObject(int id, string description) 
        { return null; }

    //Some other virtual methods in here
}

我从中派生了一些包含特定于某些 AnalysisObject 类型的行为的类。例如:

public class HWAnalysisObject : AnalysisObject {

    public override AnalysisObject CreateObject(int id, string description) 
    {
        return new HWAnalysisObject();
    }
    //override more virtual methods to provide specific behavior        
}

现在,我想编写一个可以对 AnalysisObjects 进行操作的通用服务。在此服务中,我有时需要创建并返回 AnalysisObject 的新子类型。我不知道该怎么做。

public class AOService<TAnalysisObject> where TAnalysisObject : AnalysisObject
{
    public AnalysisObject FetchObject(int id)
    {
        return TAnalysisObject.CreateObject(id, "new object");            
    }

这显然无法编译: "TAAnalysisObject 是一个类型参数,在这个上下文中是无效的。"

很公平。但是如何使用传递给我的服务的类型的属性等,以便我知道要返回什么样的子类?我觉得我在这里缺少泛型 101,这很公平,因为我通常使用泛型类和服务,我不编写它们。

我可以在服务中添加一个如下所示的方法:

private AnalysisObject MakeAnalysisObject(int id, string description)
{
    if ( (typeof(TAnalysisObject) == typeof(HWAnalysisObject) )
    {
        return new HWAnalysisObject(id, description);
    }
    if ( (typeof(TAnalysisObject) == typeof(MMAnalysisObject) )
    {
        return new MMAnalysisObject(id, description);
    }
    //etc
}

但是我觉得这违背了我尝试泛型的目的:现在我不能只派生更多的 AnalysisObject 并让服务能够处理它们:我每次添加时都必须在服务中维护这个方法一种新的类型。

【问题讨论】:

  • 你需要做where TAnalysisObject : AnalysisObject, new()然后你就可以通过new TAnalysisObject()创建对象。但是,您将只能调用无参数构造函数,而不是具有 2 个参数的构造函数。
  • 您的示例代码定义了问题陈述,但我认为它没有恰当地描述意图。如果您能提供更多关于如何使用该服务的背景信息,那就太好了。现在,您似乎计划在每次需要使用不同的分析对象时创建一个新的服务实例。那准确吗?或者您是否希望创建一个可以处理任何类型分析对象的单一服务?
  • 您在类上有一个方法,可以创建它自己的对象。要调用此方法,您首先需要创建一个对象,然后才能创建方法 CreateObject。有什么理由有这样的设计?创建具有适当参数的构造函数并为此创建工厂将是更好的设计方法。
  • @Juan - 这是一个很好的观点。该应用程序有一个服务工厂,因此我们的想法是创建一个可以处理任何类型分析对象的服务。
  • @ChetanRanpariya - 这些对象没有创建方法,直到我遇到了必须弄清楚如何创建这些对象的问题。所以我想得很好,也许我可以用这种方式创造它们。结果没有帮助。我考虑过有一个工厂,因为这看起来确实像那种问题 - 但我在这里尝试创建的是一个可以对所有这些 AnalysisObjects 进行操作的服务,当你需要一种新的 AnalysisObject 时,你只需创建一个,那是你唯一需要工作的地方。使用工厂,您必须创建对象并维护工厂。

标签: c# generics


【解决方案1】:

new() 约束意味着你的类需要有一个无参数的构造函数。然后您可以使用new T(); 创建一个新的。但是除了无参数构造函数之外,没有其他方法可以强制执行。

public class AOService<TAnalysisObject> where TAnalysisObject : AnalysisObject, new()
{
    public AnalysisObject FetchObject(int id)
    {
        return new TAnalysisObject();
    }
}

【讨论】:

  • 我接受了这个答案,因为它为我最初提出的问题提供了技术答案。我试过这个,它对我的​​直接问题很有效,尽管这意味着我必须在派生对象上实现额外的设置器。
猜你喜欢
  • 2021-10-10
  • 2022-10-15
  • 1970-01-01
  • 1970-01-01
  • 2014-04-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多