Inspired from Mark Seemann's post: Pattern Recognition: Abstract Factory or Service Locator?
I wish to write an abstract factory like so:
public interface IAbstractFactory {
T Create<T>();
}
Then, binding it using Ninject like so:
IKernel kernel = new StandardKernel();
kernel.Bind<IAbstractFactory>().ToFactory();
Then, one may use it as follows:
public class CustomerServiceIndicatorsModel {
public CustomerServiceIndicatorsModel(IAbstractFactory factory) {
this.emailIndicatorA = factory.Create<EmailIndicatorA>();
this.emailIndicatorB = factory.Create<EmailIndicatorB>();
this.emailIndicatorC = factory.Create<EmailIndicatorC>();
}
}
Again, I'm not referencing the Ninject's kernel anywhere, and this works. The kernel is only refered to in the Global.asax.cs
file for the bindings.
Can it be considered as an acceptable implementation of the abstract factory pattern?
I have a hard time trying to get the jist of this pattern. I understand the Factory
pattern clearly as being a delegated class which creates instances of a given type.
public interface IEmailIndicatorAFactory {
EmailIndicatorA Create();
}
Then, when I bind it ToFactory()
using Ninject, it shall create instances of EmailIndicatorA
.
How to bind IAbstractFactory<T>
using Ninject, since each type:
IAbstractFactory<EmailIndicatorA>
IAbstractFactory<EmailIndicatorB>
IAbstractFactory<EmailIndicatorC>
is considered a completely concrete type. And I can't find a way to bind it using Ninject
.
And I don't see any benefit of writing such an interface if in return I have to write:
public interface EmailIndicatorAFactory : IAbstractFactory<EmailIndicatorA> { }
public interface EmailIndicatorBFactory : IAbstractFactory<EmailIndicatorB> { }
public interface EmailIndicatorCFactory : IAbstractFactory<EmailIndicatorC> { }
After a comment by @PrestonGuillot, I fell in the latter implementing the ServiceLocator
instead of the AbstractFactory
as I'm using a generic Create<T>()
method, and the Abstract Factory
uses a non-generic Create()
method.
Thanks for pointing it out, @PrestonGuillot! =)
Perhaps I am overcomplicating things here... So here's my model:
EmailIndicator
public abstract EmailIndicator {
int EmailCount { get; set; }
DateTime OldestDateTimeReceived { get; set; }
}
EmailIndicatorA
public class EmailIndicatorA : EmailIndicator { }
EmailIndicatorB
public class EmailIndicatorB : EmailIndicator { }
EmailIndicatorC
public class EmailIndicatorC : EmailIndicator { }
IEmailIndicatorRepository
public interface IEmailIndicatorRepository<T> where T : EmailIndicator {
T GetIndicator();
}
public class EmailIndicatorARepository : IEmailIndicatorRepository<EmailIndicatorA> {
public EmailIndicatorARepository(IExchangeService service
, IExchangeConfiguration configuration
, INetworkCredentialFactory credentialFactory) {
exchangeService = service;
exchangeService.Url = configuration.ExchangeUri;
exchangeService = credentialFactory.Create(configuration.Login, configuration.Password);
}
EmailIndicatorA GetIndicator() {
// Code to query Exchange through its Web services here...
}
}
And two other repository like this one exist, since I have to query three different Exchange servers in my application.
I believe there is room for using the Abstract Factory
, and because I am still learning the pattern, I just don't get how to implement it yet in my situation.
If not for the indicators themselves, perhaps I can finally get a grasp on the Abstract Factory
with my reposptories.
As far as my understanding goes, here's what I would try as a first step toward a solution:
IRepositoryFactory
public interface IRepositoryFactory<T> where T : class, new() {
T Create();
}
IEmailIndicatorARepositoryFactory
public interface IEmailIndicatorARepositoryFactory
: IRepositoryFactory<EmailIndicatorARepository> {
EmailIndicatorARepository CreateEmailIndicatorARepository();
}
IEmailIndicatorBRepositoryFactory
public interface IEmailIndicatorBRepositoryFactory
: IRepositoryFactory<EmailIndicatorBRepository> {
EmailIndicatorBRepository CreateEmailIndicatorBRepository();
}
And the Abstract Factory ?
public abstract IEmailIndicatorRepositoryFactory
: IEmailIndicatorARepositoryFactory
, IEmailIndicatorBRepositoryFactory
, IEmailIndicatorCRepositoryFactory {
EmailIndicatorARepository CreateEmailIndicatorARepository() { // create instance here... }
EmailIndicatorBRepository CreateEmailIndicatorBRepository() { // create instance here... }
EmailIndicatorCRepository CreateEmailIndicatorCRepository() { // create instance here... }
}
Is this a better approach?
I'm kind of lost and confused here.