Единство МОК и шаблон фабрики, и шаблон репозитория
Я пытаюсь использовать блок Unity библиотеки enterprise в программе, которую я пишу.
Но я думаю, что использую инъекцию зависимостей неправильно. Мне было интересно, может ли кто-нибудь указать мне правильное направление.
static void Main(string[] args)
{
using (IUnityContainer container = new UnityContainer())
{
InitialiseContainer(container);
DataCopierFactory dcFactory = new DataCopierFactory();
ERunOptions dataCopierType = ExtractParams(args);
IDataCopier dataCopier = dcFactory.CreateDataCopier((int)dataCopierType, container);
dataCopier.DetectChanges();
dataCopier.ParseData();
dataCopier.CopyData();
}
}
}
//use the ioc container to register the EF context type to the repository interfaces..
private static void InitialiseContainer(IUnityContainer container)
{
//add Extensions:
container.AddNewExtension<Interception>();
//Licence Schedule
container.RegisterType<IEFContext, LTE_DownFromWeb_EFContext>("DataCopier.ScheduleDataCopier.Source");
container.RegisterType<IEFContext, LTE_Licensing_EFContext>("DataCopier.ScheduleDataCopier.Destination");
container.RegisterType<IRepositorySession>("Schedule_Source",new InjectionConstructor(container.Resolve<IEFContext>("DataCopier.ScheduleDataCopier.Source")));
container.RegisterType<IRepositorySession>("Schedule_Destination",new InjectionConstructor(container.Resolve<IEFContext>("DataCopier.ScheduleDataCopier.Destination")));
}
Таким образом, в основном Фабрика DataCopier создает экземпляр DataCopier следующим образом:
DataCopierFactory:
//return a data copier that will transfer data from any DB to any other DB
public IDataCopier CreateDataCopier(int i, IUnityContainer container)
{
switch(i)
{
case 1:
return new ScheduleDataCopier(container);
default:
throw new InvalidOperationException("Parameter " + i + " does not exist");
}
}
Копировщик данных выглядит следующим образом:
class ScheduleDataCopier : IDataCopier
{
private List<Site> _sites;
private List<SitesAndApparatuses> _scheduleList;
private IUnityContainer _container;
public ScheduleDataCopier(IUnityContainer container)
{
_container = container;
_scheduleList = new List<SitesAndApparatuses>();
}
//check if new sites registration has arrived in tblSites on down from web db.
public bool DetectChanges()
{
using (var db = _container.Resolve<IRepositorySession>("Schedule_Source"))
{
SiteAudit lastSite = new SitesAuditRepository().GetLatest();
var sitesRepo = new SitesRepository();
var sites = sitesRepo.Where(x => x.SID > lastSite.SALatestSID);
if (sites.Count() < 1)
{
return false;
}
_sites = sites.ToList();
db.Dispose();
}
return true;
}
//parse the data into a list of object SitesAndApparatuses
public bool ParseData()
{
try
{
foreach (Site s in _sites)
{
var schedule = (SitesAndApparatuses)XmlObjectBuilder.Deserialize(typeof(SitesAndApparatuses), s.XMLFile);
schedule.acCode = s.Registration.RAcCode;
_scheduleList.Add(schedule);
}
}
catch (Exception ex)
{
throw new NotImplementedException("HANDLE THIS SHIT!", ex);
}
return true;
}
public bool CopyData()
{
try
{
using (var db = _container.Resolve<IRepositorySession>("Schedule_Destination"))
{
var licensingScheduleRepo = new LicensingScheduleRepository();
//some logic
db.Commit();
}
}
catch (Exception ex)
{
}
return true;
}
}
Второй вопрос, я разрешаю свой объект unit of work, называемый RepositorySession в классах Datacopier, использующих контейнер unity, который я передал... является ли это неправильным подходом и почему, я изо всех сил пытаюсь найти любую информацию о нем в интернете?
Это, вероятно, слишком много кода для кого-то, чтобы читать.. но я надеюсь на ответ!
Заранее спасибо Нил
1 ответ:
Я бы сделал что-то вроде:
container.RegisterType<IEFContext, LTE_DownFromWeb_EFContext>("Source"); container.RegisterType<IEFContext, LTE_Licensing_EFContext>("Destination"); container.RegisterType<IRepositorySession>("Source",new InjectionConstructor(new ResolvedParameter<IEFContext>("Source")); container.RegisterType<IRepositorySession>("Destination",new InjectionConstructor(new ResolvedParameter<IEFContext>("Destination"))); container.RegisterType<IDataCopier,ScheduleDataCopier>("0",new InjectionConstructor(new[] {new ResolvedParameter<IRepositorySession("Source"),new ResolvedParameter<IRepositorySesison>("Destination")})); //Now resolve ERunOptions dataCopierType = ExtractParams(args); IDataCopier dataCopier = container.Resolve<IDataCopier(dataCopierType.ToString()); dataCopier.DetectChanges(); dataCopier.ParseData(); dataCopier.CopyData();
Класс DataCopier
Два основных различия между тем, что вы делаете, и выше заключается в том, что я использую параметры инъекции (класс ResolvedParameter) для динамического разрешения экземпляров объектов, когда они необходимы.class ScheduleDataCopier : IDataCopier { private List<Site> _sites; private List<SitesAndApparatuses> _scheduleList; private IRepositorySession _source; private (IRepositorySession _destination; public ScheduleDataCopier(IRepositorySession source, (IRepositorySession destination) { _source=source; _destination=destination; _scheduleList = new List<SitesAndApparatuses>(); } //check if new sites registration has arrived in tblSites on down from web db. public bool DetectChanges() { SiteAudit lastSite = new SitesAuditRepository().GetLatest(); var sitesRepo = new SitesRepository(); var sites = sitesRepo.Where(x => x.SID > lastSite.SALatestSID); if (sites.Count() < 1) { return false; } _sites = sites.ToList(); _source.DoSomething(); _source.CommitAndReleaseResources();//clean up but leave object reusable return true; } //parse the data into a list of object SitesAndApparatuses public bool ParseData() { try { foreach (Site s in _sites) { var schedule = (SitesAndApparatuses)XmlObjectBuilder.Deserialize(typeof(SitesAndApparatuses), s.XMLFile); schedule.acCode = s.Registration.RAcCode; _scheduleList.Add(schedule); } } catch (Exception ex) { throw new NotImplementedException("HANDLE THIS SHIT!", ex); } return true; } public bool CopyData() { try { var licensingScheduleRepo = new LicensingScheduleRepository(); //some logic _desitnation.Commit(); } catch (Exception ex) { //handle exception } return true; } }
Это позволяет мне получить Unity, чтобы сделать весь мой DI-процесс за меня, включая разрешение моего DataCopier. Если я добавлю еще один Datacopier, мне просто нужно будет добавить новый тип DataCopier в Unity с именем это соответствует соответствующему типу ERunOptions, и я смогу разрешить новый DataCopier без изменения моего кода:
container.RegisterType<IDataCopier,RandomDataCopier>("0",new InjectionConstructor(new[] {new ResolvedParameter<IRepositorySession("RandomSource"),new ResolvedParameter<IRepositorySesison>("RandomDestination")}));
И:
ERunOptions dataCopierType = ExtractParams(args); IDataCopier dataCopier = container.Resolve<IDataCopier(dataCopierType.ToString()); dataCopier.DetectChanges(); dataCopier.ParseData(); dataCopier.CopyData();
Остается прежним, но может обрабатывать ScheduledDataCopier или RandomDataCopier