Pablo
Pablo

Reputation: 2154

C# Generics - Constraints on type parameters

I'm trying to build a factory method that uses the generics feature of C#.

In this factory method I would like to constraint it to some specific classes, all of which do not have a default constructor.

Here is my example. Can someone tell me if it's possible to run it?

public class AbstractClass {
    //this abstract class does not have a default constructor, nor its subclasses
    public AbstractClass(SomeClassName obj) {
        //use obj for initialization
    }
}

//this factory class should create objects of type T that inherit 
//from AbstractClass and invoke the non-default constructor
public class FactoryClass {
    public static T BuildObject<T> (SomeClassName obj) where T: AbstractClass {
        return new T(obj); //does not work?!?!?!
    }
}


//Edit: ANSWER!!!
public static T BuildObject<T>(SomeClassUsedForTheConstructor item) where T : SomeAbstractClass { 
return (T) Activator.CreateInstance(typeof (T), item); 
} 

Upvotes: 7

Views: 1475

Answers (4)

Brian Genisio
Brian Genisio

Reputation: 48127

I like to use Activator.CreateInstance(typeof(T)) in my generics that need to create new objects of type T. It works really well.

Upvotes: 6

emptyset
emptyset

Reputation: 3244

I don't think you can instantiate generic types without a default constructor on the constraint type.

Consider instead specifying an interface IAbstractClass, such that your factory class can set the SomeClassName parameter as a property of IAbstractClass.

Additionally, if a SomeClassName instance is required for initializing AbstractClass, consider also having an empty default constructor, but a rich initializer method defined in IAbstractClass. For example:

public interface IAbstractClass { void Initialize(SomeClassName obj); }

That way, your static BuildObject method instead does:

public static T BuildObject<T>(SomeClassName obj) where T: AbstractClass 
{
  T newObject = new T();
  IAbstractClass ac = newObject as IAbstractClass;
  ac.Initialize(obj);
}

Upvotes: 4

Chris J
Chris J

Reputation: 2206

Look at the Type class and GetConstructor. Once you get the ConstructorInfo object, use the Invoke Method.

var x = typeof(T);
var t = x.GetConstructor(new[] {obj.GetType()});
object u = t.Invoke(<inputs>);

Upvotes: 4

Mark Seemann
Mark Seemann

Reputation: 233125

No, what you are trying to do is not possible using the built-in generic constraints alone. The new keyword only allows you to constrain the generic type to having a default constructor.

Upvotes: 3

Related Questions