所以,我知道StackOverflow上有很多这样的问题,但通常没有人解释他们为什么想要这样做。我希望通过这样做,更好的答案浮现出来。
这个家伙做了与我想要的接近:从Autofac容器解决通用接口的IEnumerable,但不完全一样。
我知道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;
}
}
由于明显的原因,目前的构造函数无法实现这一点。 但是是否有一种方式可以获取我想要的字典,通过或者我可以构建
<type, object>
字典的,其中object是我的各种IService<T>
?
服务查找是基于阅读DbContext
代码并简化DbContext.Set
逻辑构建的,它也受到驱动。
如果能够通过某种解析器参数获取所有IService<T>
,提取类型,并将其添加到该列表中,那么这个功能就可以使用了。
编辑:我认识到我可以注入需要构建每个服务所需的参数到ServiceLookup中,并手动构建我的列表,甚至可能是更好的答案… 但是,如果我能做到没有所有这些,那么它会更加健壮,而且我对是否可能有根本上的好奇心。
编辑2:我希望在实现中能够做到这样: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
}
}