如何在Generics中使用Factory模式?

时间:2014-03-27 22:58:37

标签: c# generics mvp factory-pattern

我希望创建一个PresenterFactory,显然对创建演示者实例负责。

基于此问题中提供的代码示例:

How to Moq this view?

和@ Pacane的回答,我以为我会这样:

PresenterFactoryTests

[TestClass]
public class PresenterFactoryTests {
    [TestClass]
    public class Instance : PresenterFactoryTests {
        [TestMethod]
        public void ReturnsInstantialized() {                
            // arrange
            Type expected = typeof(PresenterFactory);

            // act
            PresenterFactory actual = PresenterFactory.Instance;

            // assert
            Assert.IsNotNull(actual);
            Assert.IsInstanceOfType(actual, expected);
        }

        [TestMethod]
        public void ReturnsSame() {
            // arrange
            PresenterFactory expected = PresenterFactory.Instance;

            // act
            PresenterFactory actual = PresenterFactory.Instance;

            // assert
            Assert.AreSame(expected, actual);
        }
    }

    [TestClass]
    public class Create : PresenterFactoryTests {
        [TestMethod]
        public void ReturnsAuthenticationPresenter { 
            // arrange
            Type expected = typeof(IAuthenticationPresenter);

            // act
            IAuthenticationPresenter actual = 
                PresenterFactory
                    .Instance
                    .Create<IAuthenticationPresenter, IAuthenticationView>(
                        new MembershipService());

           // assert
           Assert.IsInstanceOfType(actual, expected);
        }

        // Other tests here...
    }
}

PresenterFactory

public sealed PresenterFactory {
    private PresenterFactory() { }

    public static PresenterFactory Instance { get { return getInstance(); } }

    P Create<P, V>(params object[] args) where P : IPresenter<V> where V : IView { 
        V view = (V)Activator.CreateInstance<V>();
        return Activator.CreateInstance(typeof(P), view, args);
    }

    private static PresenterFactory getInstance() {
        if (instance == null) instance = new PresenterFactory();
        return instance;
    }

    private static PersenterFactory instance;
}

ApplicationPresenter

public class ApplicationPresenter : Presenter<IApplicationView>, IApplicationPresenter {
    public ApplicationPresenter(IApplicationView view, PresenterFactory presenters)
        : base (view) {
        Presenters = presenters;

        // other initializing stuff here...
    }      
}

但是,由于类型限制,似乎我无法按照上述测试中的规定这样做。

在我的PresenterFactoryTests.Create.ReturnsAuthenticationPresenter测试方法中,当我使用接口作为类型参数时,它会编译并抛出运行时,因为Activator.CreateInstance无法创建接口的实例。

除此之外,如果我输入具体类型,它会抱怨它不能明确地将类型转换为我的类型约束,尽管它们都实现了给定的接口。

PresenterFactory需要ApplicationPresenter,我将通过其构造函数注入它,以便应用程序可以根据用户要求的功能实例化所有可用的演示者。

我错过了什么?

1 个答案:

答案 0 :(得分:2)

我认为你需要一个更通用的参数 - 具体的视图类型,因为你需要2个具体的类型(视图和演示者能够创建它们)和视图的界面类型:

P Create<P, V, IV>(params object[] args) 
      where P : IPresenter<V> where V :IV, IV: IView {