Reputation: 2154
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
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
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
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
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