views:

315

answers:

3

I have a wrapper generic class that intended to be used with a set of types. Those types are generated by a utility and are all derived from a base class ClientBase. While ClientBase has only a default constructor, all generated types have default constructor as well as a constructor takes a string as parameter. In the constructor of the wrapper class, I instantiate an instance of the type with the constructor that takes a string. Here is a sample code:

public class ClientBase
{ }

public class GenericProxy<T>
    where T: ClientBase, new()
{
    T _proxy;

    public GenericProxy(string configName)
    {
        _proxy = new T(configName);    
    }
}

This code does not compile because type T is not guaranteed to have a constructor that takes a string. Is there a way to define a constrain on the generic class to enforce that the type T must have a constructor that take a string? If this is not possible, what are good alternatives to handle this kind of situation?

+3  A: 

Unfortunately what you're trying to do isn't possible.

MSDN article on Type Constraints

Joseph
+14  A: 

It's not possible. I'd like to see "static interfaces" to handle this, but don't expect them any time soon...

Alternatives:

  • Specify a delegate to act as a factory for T
  • Specify another interface to act as a factory for T
  • Specify an interface on T itself for initialization (and add a constraint so that T implements the interface)

The first two are really equivalent. Basically you'd change your proxy class to something like this:

public class GenericProxy<T>
    where T: ClientBase, new()
{
    string _configName;
    T _proxy;
    Func<string, T> _factory;

    public GenericProxy(Func<string, T> factory, string configName)
    {
        _configName = configName;
        _factory = factory;
        RefreshProxy();
    }

    void RefreshProxy() // As an example; suppose we need to do this later too
    {
        _proxy = factory(configName);
    }
}

(I assume you're going to want to create more instances later - otherwise you might as well pass an instance of T into the constructor.)

Jon Skeet
You got my vote on the static interfaces as well
Matthew Whited
A: 

As Jon notes, there is no inbuilt support for this - but as an aside you can create a typed delegate to the constructor (faster than reflection) using Expression. The code to do this can be found in MiscUtil (in MiscUtil.Linq.Extensions.TypeExt).

Marc Gravell