11

No, this is not a question about generics.

I have a Factory pattern with several classes with internal constructors (I don't want them being instantiated if not through the factory).

My problem is that CreateInstance fails with a "No parameterless constructor defined for this object" error unless I pass "true" on the non-public parameter.

Example

// Fails
Activator.CreateInstance(type);

// Works
Activator.CreateInstance(type, true);

I wanted to make the factory generic to make it a little simpler, like this:

public class GenericFactory<T> where T : MyAbstractType
{
    public static T GetInstance()
    {
        return Activator.CreateInstance<T>();
    }
}

However, I was unable to find how to pass that "true" parameter for it to accept non-public constructors (internal).

Did I miss something or it isn't possible?

sth
  • 222,467
  • 53
  • 283
  • 367
juan
  • 80,295
  • 52
  • 162
  • 195
  • 2
    Why not define a parameterless constructor with the private boolean variable set to true? – Vivek Oct 20 '08 at 18:20

3 Answers3

21

To get around this, couldnt you just alter your usage as such:

public class GenericFactory<T> where T : MyAbstractType
{
    public static T GetInstance()
    {
        return Activator.CreateInstance(typeof(T), true);
    }
}

Your factory method will still be generic, but the call to the activator will not use the generic overload. But you should still achieve the same results.

Kilhoffer
  • 32,375
  • 22
  • 97
  • 124
3

If you absolutely require that the constructor be private you can try something like this:

public abstract class GenericFactory<T> where T : MyAbstractType
{
    public static T GetInstance()
    {
        return (T)Activator.CreateInstance(typeof(T), true);
    }
}

Otherwise you're best off adding the new constraint and going that route:

public abstract class GenericFactory<T> where T : MyAbstractType, new()
{
    public static T GetInstance()
    {
        return new T;
    }
}

You're trying to use GenericFactory as a base class for all of your factories rather than writing each from scratch right?

rpetrich
  • 32,196
  • 6
  • 66
  • 89
  • The first option is the same as that of Kilhoffer The second won't work, adding new() to the where requires the type to have a public parameter, which is exactly what I don't want – juan Sep 11 '08 at 19:58
  • Yeah, his post appeared as I was typing mine. – rpetrich Sep 11 '08 at 20:18
0

besides Activator.CreateInstance(typeof(T), true) to work, T should have default constructor