Я пытаюсь реализовать IoC в своем приложении для форм Windows. Мой выбор упал на Simple Injector, потому что он быстрый и легкий. Я также реализую единицу работы и шаблон хранилища в своих приложениях. Вот структура:
DbContext
public class MemberContext : DbContext
{
public MemberContext()
: base("Name=MemberContext")
{ }
public DbSet<Member> Members { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();\
}
}
Model
public class Member
{
public int MemberID { get; set; }
public string Name { get; set; }
}
GenericRepository
public abstract class GenericRepository<TEntity> : IGenericRepository<TEntity>
where TEntity : class
{
internal DbContext context;
internal DbSet<TEntity> dbSet;
public GenericRepository(DbContext context)
{
this.context = context;
this.dbSet = context.Set<TEntity>();
}
public virtual void Insert(TEntity entity)
{
dbSet.Add(entity);
}
}
MemberRepository
public class MemberRepository : GenericRepository<Member>, IMemberRepository
{
public MemberRepository(DbContext context)
: base(context)
{ }
}
UnitOfWork
public class UnitOfWork : IUnitOfWork
{
public DbContext context;
public UnitOfWork(DbContext context)
{
this.context = context;
}
public void SaveChanges()
{
context.SaveChanges();
}
private bool disposed = false;
protected virtual void Dispose(bool disposing)
{
if (!this.disposed)
{
if (disposing)
{
context.Dispose();
}
}
this.disposed = true;
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
}
MemberService
public class MemberService : IMemberService
{
private readonly IUnitOfWork unitOfWork;
private readonly IMemberRepository memberRepository;
public MemberService(IUnitOfWork unitOfWork, IMemberRepository memberRepository)
{
this.unitOfWork = unitOfWork;
this.memberRepository = memberRepository;
}
public void Save(Member member)
{
Save(new List<Member> { member });
}
public void Save(List<Member> members)
{
members.ForEach(m =>
{
if (m.MemberID == default(int))
{
memberRepository.Insert(m);
}
});
unitOfWork.SaveChanges();
}
}
В форме участника я добавляю только текстовое поле для ввода имени элемента и кнопки для сохранения в базе данных. Это код в форме участника:
frmMember
public partial class frmMember : Form
{
private readonly IMemberService memberService;
public frmMember(IMemberService memberService)
{
InitializeComponent();
this.memberService = memberService;
}
private void btnSave_Click(object sender, EventArgs e)
{
Member member = new Member();
member.Name = txtName.Text;
memberService.Save(member);
}
}
Я реализую SimpleInjector (см. http://simpleinjector.readthedocs.org/en/latest/windowsformsintegration.html) в Program.cs, как показано в коде ниже
static class Program
{
private static Container container;
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Bootstrap();
Application.Run(new frmMember((MemberService)container.GetInstance(typeof(IMemberService))));
}
private static void Bootstrap()
{
container = new Container();
container.RegisterSingle<IMemberRepository, MemberRepository>();
container.Register<IMemberService, MemberService>();
container.Register<DbContext, MemberContext>();
container.Register<IUnitOfWork, UnitOfWork>();
container.Verify();
}
}
Когда я запускаю программу и добавляю член, она не сохраняется в базе данных. Если я изменил container.Register
на container.RegisterSingle
, он сохранит базу данных. Из документации RegisterSingle
мой класс станет Singleton. Я не могу использовать RegisterLifeTimeScope, потому что он будет генерировать ошибку
"Зарегистрированный делегат для типа IMemberService сделал исключение. IUnitOfWork зарегистрирован как образ жизни" Срок службы ", но экземпляр запрашивается вне контекста" Срок службы "
1) Как использовать SimpleInjector в Windows Form с шаблоном UnitOfWork и Repository?
2) Правильно ли реализую шаблоны?