Question

I wish to create a PresenterFactory that would be responsible, obviously, for the creation of presenter instances.

Based on code sample provided in this question:

How to Moq this view?

and @Pacane's answer, I thought I would go this way:

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

However, because of the type constraints, it seems that I am unable to do so as stated in the test above-mentioned.

In my PresenterFactoryTests.Create.ReturnsAuthenticationPresenter test method, when I use interfaces as type parameters, it compiles and throws on runtime becuase the Activator.CreateInstance can't create an instance of an interface.

Aside, if I input the concrete types, it complains that it cannot explicitely convert type to my type constraints, albeit both implements the given interfaces.

The PresenterFactory is required by the ApplicationPresenter, I shall inject it through its constructor so that the application may instantiate all the available presenters depending on the feature being asked by the user.

What am I missing?

Was it helpful?

Solution

I think you need one more generic argument - concrete type of view because you need 2 concrete types (view and presenter to be able to create them) and type of view's interface:

P Create<P, V, IV>(params object[] args) 
      where P : IPresenter<V> where V :IV, IV: IView { 
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top