采取建设者的工厂

时间:2015-02-21 17:37:55

标签: c# interface factory

如何建立一个行为如此的工厂:

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");

我知道,我可以使用类构造函数,但这种模式可能有一些用途,我想知道这是否可行。

3 个答案:

答案 0 :(得分:1)

你可以做到,但它不漂亮。

class Factory {
    public static T Create<T>(params object[] parameters) where T : A {
        return (T) Activator.CreateInstance(typeof(T), parameters);
    }
}

虽然这看起来很有吸引力,但也有问题:

  • 你永远不会知道一个调用是否在运行时工作,它可能会引发一个讨厌的例外。
  • 参数的转换会使得很难看到哪个构造函数将被调用 - 如果有的话。
  • Activator.CreateInstance相比,
  • new非常慢。您可以使用Type.GetConstructor()直接获取构造函数,这稍快一点,但仍然很糟糕

这样的解决方案往往对自己的利益太聪明了。即使对于工厂,使用静态类型也会好得多。工厂的另一种替代方法是接受将根据需要生成实例的Func<T>

void needToUseAnAForSomething(Func<A> aCreator) {
   ...
   A a = aCreator();
}

然后客户端代码可以执行以下操作:

needToUseAnAForSomething(() => new B("test"));

在这种情况下,当然,我们可以简单地直接传递实例,但在更复杂的情况下,这可以取代工厂构造。

答案 1 :(得分:0)

这可以通过反思来实现:

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;
}

您可以通过调用以下方法调用该方法:

B test = Factory.Create<B> (new object[]{"test"});

答案 2 :(得分:0)

你可以尝试这样的事情 -

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;
            }