views:

54

answers:

2

I have a generic method that takes in a type T, which i need to be able to call a constructor on that requires a single XmlNode. Currently, I am trying to do that by having an abstract base class that has the constructors I want (plus a parameterless one so i don't have to edit the "subclasses" other than to add the actual subclassing) and constraining by that. If i try to instantiate one of these classes, it complains that it:

Cannot create an instance of the variable type 'T' because it does not have the new() constraint

and if i add the new() constraint, i get:

'T': cannot provide arguments when creating an instance of a variable type

How can i do what I want?

+1  A: 

C# Lawyer: How to Create an Instance of a Generic Type with Parameters

C# generics problem - newing up the generic type with parameters in the constructor

Leniel Macaferi
I can't use reflection, and i'd like to avoid using an Initialize function if possible. It's an option though.
RCIX
Edited answer with more options... You even answered the question of the 2nd link above : http://stackoverflow.com/questions/1682310/c-generics-problem-newing-up-the-generic-type-with-parameters-in-the-construct/1691584#1691584
Leniel Macaferi
I'll probably go with one of the suggestions at that linked SO question, thanks!
RCIX
+2  A: 

There is no way to specify that a generic type parameter T should have a constructor with a specified parameters. The fact that a base class has a constructor with some arguments doesn't help, because the overriden class doesn't have to have the same constructor (e.g. it can call the base constructor with some value as an argument).

The new() constraint can be used to require a parameter-less constructor only. I would probably suggest adding an interface constraint (e.g. IConstructFromXml) that would have a method to initialize the object - then you can call the method after you create the object using a parameterless constructor.

Alternatively, you could take a type parameter representing a factory for creating values of the specified type. Then you would create an instance of the factory and use it to create the value of the type you need. Something like:

void Foo<TFactory, T>() where TFactory : IFactory<T> 
                        where TFactory : new() {
   var factory = new TFactory();
   T val = factory.Create(xmlNode); // Create method is defined in IFactory<T>
   // ...
}

Where the IFactory<T> interface looks like this:

interface IFactory<T> {
  T Create(XmlNode node);
}   

Calling the Foo method is a bit more involved in this version, because you have to explicitly specify the factory (and you need to implement it as well), but it may be closer to what you want...

Tomas Petricek