Reputation: 7555
I am trying to implement Factory pattern
in my application.
With reference to these links, I am trying to implement but stuck at one place & not sure how to proceed.
Please find "// confused here how do I implement here" comment in my code to get where I am stuck.
//DAL Layer
public interface IReportHandler
{
IEnumerable<DocumentMapper> FetchDocumentsList(Guid clientId, int pager = 0);
}
public class ReportHandler : IReportHandler
{
public IEnumerable<DocumentMapper> FetchDocumentsList(Guid clientId, int pager = 0)
{
//implentation of the method
}
}
//BLL
public interface IReportFactory
{
IReportHandler Create(int factoryId);
}
public class ReportFactory : IReportFactory
{
private IReportHandler reportObj;
public override IReportHandler Create(int factoryId)
{
switch (factoryId)
{
case 1:
reportObj = new ReportHandler();
return reportObj;
default:
throw new ArgumentException("");
}
}
}
//UI Layer
public String GetAllDocuments(string url,int pager =0)
{
if (SessionInfo.IsAdmin)
{
string documents ;
//call GetDocumentIntoJson() private method
}
else
{
return "Sorry!! You are not authorized to perform this action";
}
}
private static string GetDocumentIntoJson(int clientId, int pager)
{
// confused here how do I implement here
IReportHandler dal = ReportFactory
var documents = dal.FetchDocumentsList(clientId, pager);
string documentsDataJSON = JsonConvert.SerializeObject(documents);
return documentsDataJSON;
}
Can somebody guide me to implement the factory pattern + improve my code-snippet?
Any help/suggestion highly appreciated.
Upvotes: 0
Views: 1882
Reputation: 776
Many people implement the Factory pattern which is violating Open-Close principle. The implementation should be allowed to extension but close for changes.
The factory class should implemented to cater all the future extension.
Factory class:
public class CalculatorFactory :ICalculatorFactory
{
private readonly IEnumerable<ICalculator> _calculators;
public CalculatorFactory(IEnumerable<ICalculator> calculators)
{
_calculators = calculators;
}
public ICalculator GetCalculator(string type)
{
var calculator = _calculators.FirstOrDefault(t => t.Name == type.ToLower());
if (calculator == null)
{
throw new NotImplementedException();
}
return calculator;
}
}
Startup:
services.RegisterAllCalculatorTypes<ICalculator>(new [] {typeof(Startup).Assembly}, ServiceLifetime.Scoped);
Extension class for DI
public static void RegisterAllCalculatorTypes<T>(this IServiceCollection services, Assembly[] assemblies,
ServiceLifetime lifetime = ServiceLifetime.Transient)
{
var typesFromAssemblies = assemblies.SelectMany(a => a.DefinedTypes.Where(x => x.GetInterfaces().Contains(typeof(T))));
foreach (var type in typesFromAssemblies)
{
services.Add(new ServiceDescriptor(typeof(T), type, lifetime));
}
}
Please check this video. It shows how to implement the Factory pattern without violating SOLID principles https://www.youtube.com/watch?v=BD-mZXOVTrU
Upvotes: 3
Reputation: 32445
Your UI layer class need instance of ReportFactory
public class UIclass
{
private readonly IReportFactory _reportFactory;
public UIclass(IReportFactory reportFactory)
{
_reportFactory = reportFactory;
}
private string GetDocumentIntoJson(int clientId, int pager)
{
// Use factory to get a ReportHandler
// You need provide "factoryId" from somewhere too
IReportHandler dal = _reportFactory.Create(factoryId);
var documents = dal.FetchDocumentsList(clientId, pager);
string documentsDataJSON = JsonConvert.SerializeObject(documents);
return documentsDataJSON;
}
}
Upvotes: 0
Reputation: 2016
Do not use such things:
IReportHandler dal = new ReportFactory();
Because it makes useless your dependency on interface and create coupling to concrete realization. Instead use Dependency Injection container and inject such factories via constructor parameters or properties. Most popular DI containers are Castle Windsor, Ninject, Unity, Autofac etc.
If you don't want to use containers - at least create all your concrete implementations in one place in program entry point, register all implementations in Service Locator (read more about it) and pass Service Locator to hierarchy via constructors.
Upvotes: 0