Constructor Autofac-基于自定义属性的构造函数参数,带有程序集扫描
我遇到了以下问题,即如何配置Autofac容器,但实际上找不到解决方案 假设我有一堆存储库,比如AccountRepository、ContactRepository、LeadRepository等等 每个存储库都有一个IService类型的构造函数参数,它提供基本CRUD方法的实现。在我的例子中,它是到第三方应用程序的通用web服务连接,但这并不重要 比如我有这样的东西:Constructor Autofac-基于自定义属性的构造函数参数,带有程序集扫描,constructor,attributes,autofac,code-injection,Constructor,Attributes,Autofac,Code Injection,我遇到了以下问题,即如何配置Autofac容器,但实际上找不到解决方案 假设我有一堆存储库,比如AccountRepository、ContactRepository、LeadRepository等等 每个存储库都有一个IService类型的构造函数参数,它提供基本CRUD方法的实现。在我的例子中,它是到第三方应用程序的通用web服务连接,但这并不重要 比如我有这样的东西: public class AccountRepository { private readonly IServic
public class AccountRepository
{
private readonly IService service;
public AccountRepository(IService service)
{
this.service = service ?? throw new ArgumentNullException(nameof(service));
}
public int GetContactCount(Guid accountId)
{
using(DataContext ctx = new DataContext(service))
{
return ctx.Contacts.Where(c => c.AccountId == accountId).Count();
}
}
}
public class UpdateNrOfContactsCommandHandler : IHandleCommand<UpdateNrOfContactsCommand, Account>
{
private readonly AccountRepository accountRepo;
private readonly AccountRepository accountRepoAsUser;
public UpdateNrOfContactsCommandHandler(AccountRepository accountRepo, [InUserContext] AccountRepository accountRepoAsUser)
{
this.accountRepo = accountRepo ?? throw new ArgumentNullException(nameof(accountRepo));
this.accountRepoAsUser = accountRepoAsUser ?? throw new ArgumentNullException(nameof(accountRepoAsUser));
}
public void Execute(Account account)
{
account.NrOfContacts = repo.GetContactCount(account.Id);
account.NrOfContactsSeenByCurrentUser = accountRepoAsUser.GetContactCount(account.Id);
}
}
我的域代码是通过命令和事件实现的。假设我有一个使用上述存储库的以下命令处理程序:
public class UpdateNrOfContactsCommandHandler : IHandleCommand<UpdateNrOfContactsCommand, Account>
{
private readonly AccountRepository accountRepo;
public UpdateNrOfContactsCommandHandler(AccountRepository accountRepo)
{
this.accountRepo = accountRepo ?? throw new ArgumentNullException(nameof(accountRepo));
}
public void Execute(Account account)
{
account.NrOfContacts = repo.GetContactCount(account.Id);
}
}
管理上下文中的服务应为默认服务
我认为一个优雅的解决方案是这样的:
public class AccountRepository
{
private readonly IService service;
public AccountRepository(IService service)
{
this.service = service ?? throw new ArgumentNullException(nameof(service));
}
public int GetContactCount(Guid accountId)
{
using(DataContext ctx = new DataContext(service))
{
return ctx.Contacts.Where(c => c.AccountId == accountId).Count();
}
}
}
public class UpdateNrOfContactsCommandHandler : IHandleCommand<UpdateNrOfContactsCommand, Account>
{
private readonly AccountRepository accountRepo;
private readonly AccountRepository accountRepoAsUser;
public UpdateNrOfContactsCommandHandler(AccountRepository accountRepo, [InUserContext] AccountRepository accountRepoAsUser)
{
this.accountRepo = accountRepo ?? throw new ArgumentNullException(nameof(accountRepo));
this.accountRepoAsUser = accountRepoAsUser ?? throw new ArgumentNullException(nameof(accountRepoAsUser));
}
public void Execute(Account account)
{
account.NrOfContacts = repo.GetContactCount(account.Id);
account.NrOfContactsSeenByCurrentUser = accountRepoAsUser.GetContactCount(account.Id);
}
}
public class InUserContextAttribute : Attribute
{
}
public class AccountRepository
{
private readonly IService service;
public AccountRepository(IService service)
{
this.service = service ?? throw new ArgumentNullException(nameof(service));
}
public int GetContactCount(Guid accountId)
{
using(DataContext ctx = new DataContext(service))
{
return ctx.Contacts.Where(c => c.AccountId == accountId).Count();
}
}
}
public class UpdateNrOfContactsCommandHandler : IHandleCommand<UpdateNrOfContactsCommand, Account>
{
private readonly AccountRepository accountRepo;
private readonly AccountRepository accountRepoAsUser;
public UpdateNrOfContactsCommandHandler(AccountRepository accountRepo, [InUserContext] AccountRepository accountRepoAsUser)
{
this.accountRepo = accountRepo ?? throw new ArgumentNullException(nameof(accountRepo));
this.accountRepoAsUser = accountRepoAsUser ?? throw new ArgumentNullException(nameof(accountRepoAsUser));
}
public void Execute(Account account)
{
account.NrOfContacts = repo.GetContactCount(account.Id);
account.NrOfContactsSeenByCurrentUser = accountRepoAsUser.GetContactCount(account.Id);
}
}
公共类updateNofContactsCommandHandler:IHandleCommand
{
私有只读AccountRepository accountRepo;
私有只读AccountRepository AccountRepositor;
公共更新ContactsCommandHandler(AccountRepository accountRepo,[InUserContext]AccountRepository AccountRepasUser)
{
this.accountRepo=accountRepo??抛出新的ArgumentNullException(nameof(accountRepo));
this.accountRepoAsUser=accountRepoAsUser??抛出新的ArgumentNullException(nameof(accountRepoAsUser));
}
公共作废执行(账户)
{
account.NrOfContacts=repo.GetContactCount(account.Id);
account.NrOfContactsSeenByCurrentUser=accountrepoasser.GetContactCount(account.Id);
}
}
我试图实现的目标是可能的吗?怎么做?;) 你有很多选择来实现你的目标,我更喜欢的是使用 为了使用命名服务,您需要注册两个
IService
实现:
//使用字符串使事情简单化
//首先注册您的服务
builder.RegisterType()。命名为(“admin”);
builder.RegisterType()。命名为(“用户”);
//然后注册存储库,两次:
foreach(assembly.GetTypes.Where(t=>IsRepository(t))中的var repoType)
{
builder.RegisterType(repoType)
.WithParameter(新解析参数(
(pi,ctx)=>pi.ParameterType==typeof(iSeries设备),
(pi,ctx)=>ctx.ResolveNamed(“admin”))
。名为(“管理员”);
builder.RegisterType(repoType)
.WithParameter(新解析参数(
(pi,ctx)=>pi.ParameterType==typeof(iSeries设备),
(pi,ctx)=>ctx.ResolveNamed(“用户”))
.指定(“用户”);
}
在存储库构造函数中,您可以:
public UpdateNrOfContactsCommandHandler([KeyFilter(“admin”)]accountRepo、[KeyFilter(“user”)]AccountRepository accountrepasuser)
{
this.accountRepo=accountRepo??抛出新的ArgumentNullException(nameof(accountRepo));
this.accountRepoAsUser=accountRepoAsUser??抛出新的ArgumentNullException(nameof(accountRepoAsUser));
}
您还可以使用其他技术,例如实现解析逻辑的额外类,如下所示:
public class AccountRepository
{
private readonly IService service;
public AccountRepository(IService service)
{
this.service = service ?? throw new ArgumentNullException(nameof(service));
}
public int GetContactCount(Guid accountId)
{
using(DataContext ctx = new DataContext(service))
{
return ctx.Contacts.Where(c => c.AccountId == accountId).Count();
}
}
}
public class UpdateNrOfContactsCommandHandler : IHandleCommand<UpdateNrOfContactsCommand, Account>
{
private readonly AccountRepository accountRepo;
private readonly AccountRepository accountRepoAsUser;
public UpdateNrOfContactsCommandHandler(AccountRepository accountRepo, [InUserContext] AccountRepository accountRepoAsUser)
{
this.accountRepo = accountRepo ?? throw new ArgumentNullException(nameof(accountRepo));
this.accountRepoAsUser = accountRepoAsUser ?? throw new ArgumentNullException(nameof(accountRepoAsUser));
}
public void Execute(Account account)
{
account.NrOfContacts = repo.GetContactCount(account.Id);
account.NrOfContactsSeenByCurrentUser = accountRepoAsUser.GetContactCount(account.Id);
}
}
公共类工厂
{
专用ILifetimeScope\u范围;
公共RepoFactory(ILifetimeScope范围)
{
_范围=范围;
}
公共类RepoContext:IDisposable
{
公共T实例{get;}
公共空间处置()
{
//实例处理
}
}
公共RepoContext AsAdmin()
{
var service=scope.ResolveNamed(“admin”);
//保持简单,如果需要,您可以利用更多Autofac来提高性能
var repo=Activator.CreateInstance(typeof(T),service);
返回新的repo上下文(repo);
}
}
回答我自己的问题,因为我找到了一种方法。基本上,解决方案(实际上并不复杂)包括使用Autofac的.Resolve()方法的ResolvedParameter参数
它允许您将特定参数注入正在解析的对象
如果有人感兴趣,下面就是我使用的确切代码。
注意-这是在考虑CRM系统的情况下进行的。“服务连接”类型为IOOrganizationService,我上面提到的“存储库”称为“查询”,为使其正常工作,应全部继承自名为CrmQuery公共抽象类CrmQuery,其中tenty:Entity
{
示例查询类如下所示:
public class AccountRepository
{
private readonly IService service;
public AccountRepository(IService service)
{
this.service = service ?? throw new ArgumentNullException(nameof(service));
}
public int GetContactCount(Guid accountId)
{
using(DataContext ctx = new DataContext(service))
{
return ctx.Contacts.Where(c => c.AccountId == accountId).Count();
}
}
}
public class UpdateNrOfContactsCommandHandler : IHandleCommand<UpdateNrOfContactsCommand, Account>
{
private readonly AccountRepository accountRepo;
private readonly AccountRepository accountRepoAsUser;
public UpdateNrOfContactsCommandHandler(AccountRepository accountRepo, [InUserContext] AccountRepository accountRepoAsUser)
{
this.accountRepo = accountRepo ?? throw new ArgumentNullException(nameof(accountRepo));
this.accountRepoAsUser = accountRepoAsUser ?? throw new ArgumentNullException(nameof(accountRepoAsUser));
}
public void Execute(Account account)
{
account.NrOfContacts = repo.GetContactCount(account.Id);
account.NrOfContactsSeenByCurrentUser = accountRepoAsUser.GetContactCount(account.Id);
}
}
公共类accountquerys:CrmQuery
{
公共帐户查询(IOOrganizationService orgService):基本(orgService){}
public Something[]GetSomething(Guid accountId)
{
//...
}
}
现在,这个查询在命令处理程序中使用(siml