Общий репозиторий 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 знает, как их создать, он будет предоставлять их конструктору во время процесса разрешения.