2012-05-20 3 views
0

IoC 컨테이너 (Unity)를 사용하여 인터페이스를 등록하고 개체를 확인/인스턴스화합니다.IoC 디자인 - 동적 위임 서비스 용 서비스 내 참조 서비스 로케이터

잘 작동하고 인터페이스에 종속 된 모든 클래스가 생성자에 삽입되지만 디자인 문제가 발생합니다.

특정 시간에 등록 된 대리자를 호출하는 CronJob 서비스가 있으며 서비스 로케이터에 의해 인스턴스화됩니다.

작업을 등록 할 수 있기 때문에 서비스 로케이터 Unity 컨테이너를 인스턴스화 된 클래스 내에서 참조하고 있습니다. 작업을 동적으로 등록 할 수 있기 때문에 컴파일 타임에 어떤 객체가 생성자에 전달 될지 모르기 때문에이 작업을 수행하고 있습니다. .

비록 IoC와 통합에 익숙하지 않지만 서비스 내에서 정적 서비스 로케이터를 참조하는 것이 좋지 않기 때문에 모든 종속성을 생성자에 전달해야합니다. 다른 방법에 대한 생각을 고맙게 생각합니다. 이 경우 서비스 로케이터를 참조하는 것이 좋습니까?

감사합니다,

크리스

코드는 다음과 같습니다 : 유니티를 사용

서비스 로케이터

// ServiceManager provides service location facilities, logging facilities, and database access via IUnitOfWork interface 
public class ServiceManager 
{ 
    private static readonly UnityContainer m_ServicesContainer = new UnityContainer(); 
    private static readonly ServiceManager m_Manager = new ServiceManager(); 
    public static ServiceManager Instance { get { return m_Manager; } } 
    private ILogger Logger { get { return Resolve<ILogger>(); } } 

    public T Resolve<T>() 
    { 
     return m_ServicesContainer.Resolve<T>(); 
    } 

    private ServiceManager() 
    { 
     // register the unit of work class first!! 
     RegisterType<IUnitOfWork, UnitOfWork>(); 
     // always register the logger (without logging) 
     RegisterType<ILogger, NLogForEntityFrameworkLogger>(true); 
     // always register the settings manager (without logging) 
     RegisterType<ISettingsService, SettingsService>(); 
     RegisterType<IPluginManagerService, PluginManagerService>(true); 
     RegisterType<ICronJobService, CronJobService>(true); 
     RegisterType<IReminderGeneratorService, ReminderGeneratorService>(); 
     RegisterType<IInvoiceService, InvoiceService>(); 
    } 

    public void RegisterType<TFrom, TTo>(bool isSingleton = false) 
    { 
     if (isSingleton == false) 
      m_ServicesContainer.RegisterType(typeof(TFrom), typeof(TTo)); 
     else 
      m_ServicesContainer.RegisterType(typeof(TFrom), typeof(TTo), new ContainerControlledLifetimeManager()); 

    } 
} 

cronjob를 클래스

public static class CronJobDelegates 
{ 
    public static void SyncRecords(BusinessUnit businessUnit) 
    { 
     ISynchronisationService syncService = ServiceManager.Instance.Resolve<ISynchronisationService>(); 
     syncService.Sync(businessUnit); 
    } 
} 

class CronJobService : ServiceBaseWithUnitOfWork, ICronJobService 
{ 
    public CronJobService(IUnitOfWork unitOfWork, ILogger logger, ISettingsService settings) 
     : base(unitOfWork, logger) 
    { 
     m_Settings = settings; 
     RegisterCronJob("SyncAccountRecords", CronJobDelegates.SyncRecords,"*1****"); 
    } 

    ISettingsService m_Settings; 

    public class RegisteredCronJob 
    { 
     public RegisteredCronJob(string jobName, EventJobDelegate job) 
     { 
      JobName = jobName; 
      Job = job; 
     } 

     public string JobName { get; private set; } 
     public EventJobDelegate Job { get; private set; } 
    } 

    static object Lock = new object(); 

    Dictionary<string, EventJobDelegate> CronJobs = new Dictionary<string, EventJobDelegate>(); 

    public void RegisterCronJob(string jobName, EventJobDelegate jobCallback, string jobSetting) 
    { 
     lock(Lock) 
     { 
      if(CronJobs.ContainsKey(jobName)) 
      { 
       LogMessage("Job '" + jobName + "' already registered", LogLevel.Warn); 
       // warning job already registered 
      } 
      else 
      { 
       CronJob cronJobRecord = UnitOfWork.CronJobRepository.GetByID(jobName); 

       if (cronJobRecord == null) 
       { 
        CronJob newCronJob = new CronJob() 
        { 
         JobName = jobName, 
         JobSetting = jobSetting 
        }; 
        UnitOfWork.CronJobRepository.Insert(newCronJob); 
       } 
       else 
        jobSetting = cronJobRecord.JobSetting; 

       LogMessage("Job '" + jobName + "' registered using settings: " + jobSetting + ". Next run due on UTC " + NCrontab.CrontabSchedule.Parse(jobSetting).GetNextOccurrence(DateTime.UtcNow), LogLevel.Info); 

       CronJobs.Add(jobName, jobCallback); 
       UnitOfWork.Save(); 
      } 
     } 
    } 

    public void ProcessEvents() 
    { 
     foreach(BusinessUnit businessUnit in UnitOfWork.BusinessUnitRepository.Get()) 
     { 
      foreach (CronJob cronJob in UnitOfWork.CronJobRepository.Get()) 
      { 
       lock(Lock) 
       { 
        NCrontab.CrontabSchedule schedule = NCrontab.CrontabSchedule.Parse(cronJob.JobSetting); 

        if (schedule.GetNextOccurrence(cronJob.LastRan) > DateTime.UtcNow.AddHours(businessUnit.GmtOffset)) 
        { 
         EventJobDelegate jobDelegate; 
         if (CronJobs.TryGetValue(cronJob.JobName, out jobDelegate) == true) 
         { 
          jobDelegate(businessUnit); 
          cronJob.LastRan = DateTime.UtcNow; 
          UnitOfWork.CronJobRepository.Update(cronJob); 
          LogMessage("Job '" + cronJob.JobName + "' ran, next schedule on " + schedule.GetNextOccurrence(cronJob.LastRan)); 
         } 
        } 
       } 
      } 
     } 
     UnitOfWork.Save(); 
    } 
} 

답변

1

팩토리를 삽입하면 SyncRecords에서와 같이 컨테이너를 호출하는 ISynchronisationService의 인스턴스를 확인할 수 있습니다.

공장 접근 방법을 구현하는 예는 here을 참조하십시오. 여기에는 여러 가지 대안이 나와 있습니다.