Reputation: 773
How can I make a factory that behaves like this:
interface A {
}
class B: A {
string b;
public B(string b) { this.b = b; }
}
class Factory {
public static T create<T>(/*somehow pass constructor parameters*/) where T: A {
return new T(/*constructor parameters*/);
}
}
B test = Factory.create<B>("test");
I know, I can just use class constructor, but this pattern may have some uses and I want to know if this is possible.
Upvotes: 0
Views: 98
Reputation: 28809
You can do it, but it ain't pretty.
class Factory {
public static T Create<T>(params object[] parameters) where T : A {
return (T) Activator.CreateInstance(typeof(T), parameters);
}
}
Although this may look superficially attractive, there are problems:
Activator.CreateInstance
is very slow compared to new
. You can get the constructor directly using Type.GetConstructor()
, which is marginally faster, but it still sucks.Solutions like this tend to be too clever for their own good. You are really much better off using static typing, even with factories. One alternative to a factory is accepting a Func<T>
that will produce an instance on demand:
void needToUseAnAForSomething(Func<A> aCreator) {
...
A a = aCreator();
}
And then client code can do something like this:
needToUseAnAForSomething(() => new B("test"));
In this case, of course, we could simply pass the instance directly, but in more complicated scenarios this could take the place of a factory construction.
Upvotes: 1
Reputation: 40
You can try something like this -
public static object create<T>(string param) where T : A
{
Type type = typeof(T);
ConstructorInfo ctor = type.GetConstructor(new[] { typeof(string) });
object instance = ctor.Invoke(new object[] { param });
return instance;
}
Upvotes: 0
Reputation: 12064
This can bei achieved with reflection:
public static T Create<T> (object[] parameters) where T : class
{
Type[] parameterTypes = (parameters ?? Enumerable.Empty<object> ())
.Select (parameter => parameter.GetType ()).ToArray ();
ConstructorInfo ctor = type.GetConstructor (parameterTypes);
Debug.Assert (ctor != null);
T instance = ctor.Invoke (parameters) as T;
Debug.Assert (instance != null);
return instance;
}
You Invoke that method by calling:
B test = Factory.Create<B> (new object[]{"test"});
Upvotes: 0