Общий репозиторий Loc

Я изучаю Entity Framework и пробую общий репозиторий с рабочим шаблоном. Используя Замок Виндзор, я делаю все через интерфейсы.

Однако единица работы свойства InternetRepository тесно связана:

public interface IUnitOfWork
{
    IGenericRepository<RecordInternetSpeed> InternetSpeedRepository { get; }
    void Save();
}

public class UnitOfWork :IUnitOfWork, IDisposable
{
    private bool disposed = false;
    private InternetSpeedEntities context = new InternetSpeedEntities();

    private IGenericRepository<RecordInternetSpeed> internetSpeedRepository;
    public IGenericRepository<RecordInternetSpeed> InternetSpeedRepository
    {
        get
        {
            if(this.internetSpeedRepository == null)
            {
                this.internetSpeedRepository = new GenericRepository<RecordInternetSpeed>(context);
            }
            return internetSpeedRepository;
        }
    }

    public void Save()
    {
        context.SaveChanges();
    }

    protected virtual void Dispose(bool disposing)
    {
        if (!this.disposed)
        {
            if (disposing)
            {
                context.Dispose();
            }
        }
        this.disposed = true;
    }

    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }
}

Как ввести это свойство для использования интерфейса? Далее ниже как IUnitOfWork называется:

    private Timer timer;
    private ICalculateInternetSpeed internetSpeed;
    private IUnitOfWork unitOfWork;

    public MyRunner(ICalculateInternetSpeed internetSpeed, IUnitOfWork unitOfWork)
    {
        this.internetSpeed = internetSpeed;
        this.unitOfWork = unitOfWork;
    }

    public void Start()
    {
        timer = new Timer
                    {
                        //1000 (1 sec)
                        Interval = 5000,
                        Enabled = true
                    };

        timer.Elapsed += (TimerElapsed);
    }

   public void Stop()
   {

   }

   private void TimerElapsed(object sender, ElapsedEventArgs e)
   {
       try
       {
           timer.Enabled = false;
           //Kick off method to get the download speed
           var speed = internetSpeed.CalculateInternetDownloadSpeed();
           Logger.Logger.Info("Internet Speed calculated.");
           unitOfWork.InternetSpeedRepository.Insert(speed);
           unitOfWork.Save();
           Logger.Logger.Info(string.Format("Inserted record with ID {0} into the database.", speed.RecordId));
       }
       catch (Exception ex)
       {
           Logger.Logger.Error(ex.ToString());
       }
       finally
       {
           timer.Enabled = true;
       }
   }
}

Затем он вызывается внутри основного класса моей программы:

private static void Main(string[] args)
    {
        container = new WindsorContainer(new XmlInterpreter());
        container.Install(FromAssembly.This());
        var runner = container.Resolve<IMyRunner>();

        HostFactory.Run(x =>
            {
                x.Service<IMyRunner>(s =>
                    {
                        s.SetServiceName(ServiceName);
                        s.ConstructUsing(c => runner);
                        s.WhenStarted(tc => tc.Start());
                        s.WhenStopped(tc =>
                            {
                                tc.Stop();
                                container.Release(runner);
                            });
                    });

                x.RunAsLocalSystem();
                x.SetDescription(ServiceDescription);
                x.SetDisplayName(ServiceDisplayName);
                x.SetServiceName(ServiceName);
                x.StartAutomatically();

            });
    }

Последний фрагмент кода, который я считаю необходимым, - это мой класс установщика:

public class Installer : IWindsorInstaller
{
    public void Install(IWindsorContainer container, IConfigurationStore store)
    {
        container.Register(Component.For<IMyRunner>().ImplementedBy<MyRunner>().LifeStyle.Transient,
                           Component.For<ICalculateInternetSpeed>().ImplementedBy<CalculateInternetSpeed>().LifeStyle.Transient,
                           Component.For<IUnitOfWork>().ImplementedBy<UnitOfWork>().LifeStyle.Transient,
                           Component.For<ISimpleWebClient>().ImplementedBy<SimpleWebClient>(),
                           Component.For<IConfig>().ImplementedBy<Config>(),
                           Component.For<IGenericRepository<RecordInternetSpeed>>().ImplementedBy<GenericRepository<RecordInternetSpeed>>());
    }
}

Как вы можете видеть, я пытался ввести его здесь, но не уверен, что это сработает. Это правильный способ сделать инъекцию свойства?

1 ответ

Во-первых, не забудьте зарегистрироваться InternetSpeedEntities также.
Тогда либо прими IGenericRepository<RecordInternetSpeed> в качестве параметра в конструкторе Unit of Work и установите личное поле, или преобразуйте это свойство в автоматическое свойство с помощью getter и setter, и Castle Windsor сделает всю работу за вас.

Несколько других заметок, хотя:

  • Попробуйте привыкнуть к регистрации ваших компонентов с помощью соглашений (например, container.Register( Classes.FromThisAssembly() .Pick().WithServiceDefaultInterfaces()
    );
    ) Таким образом, вам не нужно делать все вручную..
  • Обратите внимание на стиль жизни ваших компонентов. Если вы не укажете один - по умолчанию это синглтон. Они не будут утилизированы, пока контейнер не будет утилизирован. В качестве альтернативы вы можете связать образ жизни компонента с родительским типом объекта в графе объектов.

Надеюсь это поможет. Удачи!

-РЕДАКТИРОВАТЬ-

Как пример, ваш UnitOfWork может выглядеть так:

public class UnitOfWork : IUnitOfWork, IDisposable
{
    public UnitOfWork(GenericRepository<RecordInternetSpeed> repository, InternetSpeedEntities context)
    {
        this.context = context;
        this.InternetSpeedRepository = repository;
    }

    private bool disposed = false;
    private InternetSpeedEntities context;

    public IGenericRepository<RecordInternetSpeed> InternetSpeedRepository { get; private set; }

    ...

} 

И ваш установщик может выглядеть примерно так:

public class Installer : IWindsorInstaller
{
    public void Install(IWindsorContainer container, IConfigurationStore store)
    {
        container.Register(
            Classes.FromThisAssembly()
            .Pick().WithServiceDefaultInterfaces()
            .LifestyleTransient()
            );
    }
}  

Хранилище и контекст являются зависимостями вашего UnitOfWork, Пока windsor знает, как их создать, он будет предоставлять их конструктору во время процесса разрешения.

Другие вопросы по тегам