views:

6635

answers:

3

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?

+10  A: 

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
Nice workaround, but I'd like to know if it's possible also
Juan Manuel
If the overload doesn't exist, I would have to say no.
Kilhoffer
+2  A: 

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
The first option is the same as that of KilhofferThe 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 Manuel
Yeah, his post appeared as I was typing mine.
rpetrich
A: 

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

mpastern