【发布时间】:2019-12-19 15:06:16
【问题描述】:
所以,我承认 StackOverflow 中充斥着这个问题,但通常没有人解释他们为什么要这样做。我希望通过这样做,一个更好的答案会浮到顶部。
这家伙做了一些接近我想要的事情:Resolving IEnumerable of generic interfaces from Autofac container 但不完全是。
我知道IGenericInterface<ObjectA> 不等于IGenericInterface<ObjectB>。
话虽如此,我很想将每个 IService<T> 注入到一个构造函数中,以便我可以构建查找。老实说,我想构建一个与DbContext.Set<T> 非常相似的实现
我的问题中的几个关键人物。
public interface IService<TMessage> where TMessage: IContractDTO
{
IQueryable<TMessage> BuildProjection();
}
目前我一次注射这些
public class SomeController : BaseODataController<SomeEntityDTO>
{
public SomeController(IControllerServiceContext context, IService<SomeEntityDTO> service)
: base(context, service)
{
}
//DO STUFF
}
IControllerServiceContext 是与DbContext、AppSettings 以及我希望在每个控制器中使用的其他一些常用功能的复合接口。
在大多数情况下,这已经足够了。但是偶尔为了支持 EntityA 的逻辑,我可能需要对 B 进行快速查找。我宁愿使用 IService<SomeEntityB> 的 BuildProjections() 实现而不是在控制器 A 中构建冗余。如果我注入每个我有一些这样可以成为 8 或 9 参数的构造函数,例如
所以我开始思考,如果我能够将 IServiceLookup 添加到 IControllerServiceContext,那么我将拥有我需要的一切。
我是从这条路开始的:
public class ServiceLookup<TContract>: IServiceLookup where TContract: BaseClass, IContractDTO
{
public ServiceLookup(IEnumerable<IService<TContract>> services)
{
//Build _Services
}
private readonly IDictionary<Type, object> _services;
public IService<TMessage> Service<TMessage>() where TMessage : class, IContractDTO
{
return (IService<TMessage>)(GetService(typeof(TMessage)));
}
private object GetService(Type type)
{
_services.TryGetValue(type, out var service);
return service;
}
}
由于明显的原因,当前的构造函数无法做到这一点。
但是有没有办法通过IIndex 或IEnumerable 获得我想要的字典,我可以构建<type, object> 的字典,其中对象是我的各种IService<T>?
服务查找是基于读取DbContext 代码并简化DbContext.Set 的逻辑而构建的,这也是由IDictionary<Type, object> 驱动的。
如果通过某种解析器参数我可以获得所有IService<T>s,提取T 类型,并将它们添加到该列表中,我就可以参加比赛了。
编辑:我知道我可以注入构建每个服务所需的参数
进入ServiceLookup 并手动构建我的列表,这甚至可能是更好的答案......但如果我可以在没有所有这些的情况下做到这一点,它会更加强大,而且我基本上好奇 em>如果可能的话
Edit2:我希望在实现中能够做的事情如下所示:
public SomeController(IControllerServiceContext context, IServiceLookup lookup)
: base(context, service)
{
public SomeMethod() {
var x = lookup.Service<EntityOneDTO>().BuildProjections().FirstOrDefault();
var y = lookup.Service<EntityTwoDTO>().BuildProjections().FirstOrDefault();
//Do Logic that requires both EntityOne and EntityTwo
}
}
【问题讨论】:
-
我不明白你想要做什么。根据我的理解,我制作了这个样本:dotnetfiddle.net/Widget/nGlqm1,它可以工作。你能解释更多你想要做什么吗?
-
@CyrilDurand - 我添加了一些细节。您的示例与我要去的地方有点倒退。我有 Service1: IService
和 Service2: IService
标签: c# dependency-injection autofac