Единство МОК и шаблон фабрики, и шаблон репозитория


Я пытаюсь использовать блок 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 2

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

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;
    }
}
Два основных различия между тем, что вы делаете, и выше заключается в том, что я использую параметры инъекции (класс ResolvedParameter) для динамического разрешения экземпляров объектов, когда они необходимы.

Это позволяет мне получить 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