user2316154
user2316154

Reputation: 334

How do I actually use a generic type in my generic service to create new objects?

NOTE: In order to write a reasonably short question, I create an example similar to the troubled area of my application. The actual example is more complex but the problem statement is accurate.

Say I have an abstract base class:

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

    //Some other virtual methods in here
}

I derive some classes from it that contain behavior specific to some AnalysisObject types. For example:

public class HWAnalysisObject : AnalysisObject {

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

Now, I want to write a generic service that can operate on AnalysisObjects. In this service I at some point need to create and return new subtypes of AnalysisObject. And I can't figure out how to do that.

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

That does not compile, obviously: "TAnalysisObject is a type parameter, which is not valid in this context."

Fair enough. But how can I use the properties, etc of the type that I pass in to my service so I know what kind of subclass to return? I feel like I'm missing Generics 101 here, which is fair enough because I usually use generic classes and services, I do not write them.

I could stick a method in the service that looks like this:

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
}

But I feel that defeats the purpose of why I tried generics: now I can't just derive more AnalysisObject and have the service just able to take care of them: I have to maintain this method in the service every time I add a new type.

Upvotes: 1

Views: 166

Answers (1)

nvoigt
nvoigt

Reputation: 77304

The new() constraint means your class needs to have a parameterless constructor. Then you can create a new one with new T();. There is no way to enforce another than the parameterless constructor though.

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

Upvotes: 2

Related Questions