目前,我的代码与此类似(缩写只是为了说明一点):
存储库接口
public interface IRepository<TEntity, in TKey>
{
IList<TEntity> GetAll();
TEntity Get(TKey id);
TEntity Add(TEntity item);
TEntity Update(TEntity item);
bool Remove(TKey id);
}
基本EF存储库
public class BaseEFRepository<TEntity, TKey> : IRepository<TEntity, TKey> where TEntity: class, IEntity<TKey> where TKey: struct
{
protected readonly DbContext _dbContext;
public BaseRepository()
{
_dbContext = new MyDB();
_dbContext.Configuration.ProxyCreationEnabled = false;
_dbContext.Configuration.LazyLoadingEnabled = false;
}
public virtual TEntity Get(TKey id)
{
return _dbContext.Set<TEntity>().Find(id);
}
public virtual IList<TEntity> GetAll()
{
return _dbContext.Set<TEntity>()
.ToList();
}
public virtual TEntity Add(TEntity item)
{
_dbContext.Set<TEntity>().Add(item);
_dbContext.SaveChanges();
return item;
}
.....
.....
}
基础存储库的示例实现
public interface IContactsRepository : IRepository<Contact, long>
{
Contact GetByEmployeeId(string empId, ContactType type);
IList<Contact> GetByEmployeeId(string empId);
}
public class ContactsRepository : BaseEFRepository<Contact, long>, IContactsRepository
{
public Contact GetByEmployeeId(string empId, ContactType type)
{
var contact = _dbContext.Set<Contact>()
.FirstOrDefault(d => d.EmployeeId == empId && d.ContactType == type);
return contact;
}
public IList<Contact> GetByEmployeeId(string empId)
{
var contacts = _dbContext.Set<Contact>()
.Where(d => d.EmployeeId == empId)
.ToList();
return contacts;
}
}
public class Contacts
{
public Contact Get(long id)
{
IContactsRepository repo = ResolveRepository<IContactsRepository>();
var contact = repo.Get(id);
return contact;
}
public Contact GetByEmployeeId(string empId, ContactType type)
{
IContactsRepository repo = ResolveRepository<IContactsRepository>();
return repo.GetByEmployeeId(empId, type);
}
.......
.......
}
现在,一切都很好。我可以简单地做这样的事情:
var _contacts = new Contacts();
var contact = _contacts.GetByEmployeeId("C1112", ContactType.Emergency);
当我阅读this blog post时,混淆开始,作者说使用如下代码:
IContactsRepository repo = ResolveRepository<IContactsRepository>();
是一种糟糕的技术,它是反模式的,应该在代码的根源处注入所有内容。我无法看到如何使用存储库模式执行此操作。我正在使用WCF消费它。那么,我将如何从WCF的第一次调用中注入所有内容?我无法得到它。我在这里缺少什么?
最后一点,在这种情况下,WCF是最后一层,它应该只知道它之前的层,即BLL层。如果我要按照该博客的作者建议实现任何内容,我会让WCF层知道DAL层,这不是那么糟糕的做法吗?如果我错了,请纠正我。
答案 0 :(得分:3)
您需要使用构造函数注入,然后在Composition Root中编写对象。
当您使用构造函数注入时,您通过构造函数注入依赖项,因此您的类看起来像这样:
public class BaseRepository
{
protected readonly DbContext _dbContext;
//...
public BaseRepository(DbContext context)
{
_dbContext = context;
}
//...
}
public class ContactsRepository : BaseEFRepository<Contact, long>, IContactsRepository
{
//...
public ContactsRepository(DbContext context)
:base(context)
{
}
//...
}
public class Contacts
{
private readonly IContactsRepository m_ContactsRepository;
public Contacts(IContactsRepository contacts_repository)
{
m_ContactsRepository = contacts_repository;
}
public Contact Get(long id)
{
var contact = m_ContactsRepository.Get(id);
return contact;
}
//...
}
然后在Composition Root中,您将把所有对象组合在一起。可选择通过DI容器。
以下是使用Pure DI:
的此类合成示例var context = new MyDB();
context.Configuration.ProxyCreationEnabled = false;
context.Configuration.LazyLoadingEnabled = false;
var contacts = new Contacts(new ContactsRepository(context));
在IIS中托管的WCF应用程序中,“合成根”是自定义ServiceHostFactory
。 This answer提供了有关如何执行此操作的详细信息。
答案 1 :(得分:2)
您需要识别适合用作合成根的接缝。
对于WCF,您需要获得广告素材 - 您必须创建自定义ServiceHostFactory
来截取正确的位置以构建对象根目录。
请参阅Mark Seemann的例子this article和this article(“.Net中的依赖注入”一书的作者 - 我认为您会发现这本书非常有用)。
许多免费的DI容器such as Autofac为WCF提供了现成的支持,这可能是最好的方法。
我真的不能足够推荐Seemann的书 - 它详细介绍了这一点。
您可能还会发现this article on using Autofac DI with ASP.Net and a repository有趣。
答案 2 :(得分:2)
@ Matthew的帖子应该回答你的问题。但是,我想提一下我在代码中注意到的与问题相关的一件事。您不应该尝试手动解决依赖关系,但应该由容器注入。我修改了您的代码以显示此行为:
public class Contacts
{
private IContactsRepository repo;
public Contacts(IContactsRepository injectedContactsRepository)
{
repo = injectedContactsRepository;
}
public Contact Get(long id)
{
var contact = repo.Get(id);
return contact;
}
//and other methods definitions...
}