【发布时间】:2019-04-09 13:30:42
【问题描述】:
我已尽我所能解释我公认的复杂问题。让我知道是否有任何我可以添加澄清的内容。
简要背景
我有一个DbWrapperCollection 用来存储DbWrapper<TInput. TOutput>(因为TInput 和TOutput 会有所不同,所以集合实际上只是一个包含泛型作为对象的非泛型“容器”列表作为输入和作为 System.Types 输出 - 请参阅下面的实现)
另一方面,我有数量不定的服务,它们都有自己的IDbWrapperCollection,我想在启动时使用 autofac 注入这些服务。
基本上我想做的是:
builder.RegisterType<SaveApplDbWrapper>().As<DbWrapper<AppleDto, SavedAppleDbEntity>>()
.Named<string>("fruitService");
builder.RegisterType<SaveOrangeDbWrapper>().As<IUcHandler<OrangeDto, OrangeDbEntity>>()
.Named<string>("fruitService");
builder.RegisterType<SaveMelon>().As<IUcHandler<MelonDto, MelonDbEntity>>()
.Named<string>("appleService");
builder.Register(c => new FruitService(c.ResolveNamed("appleService")))
.As<IDbMapperService>();
我的问题
正如您在上面看到的,我在调用ResolveNamed() 时专门省略了预期的类型参数。那是因为我是 autofac 的新手(在某种程度上,泛型),我特别不知道是否有任何策略可以注入一个开放的泛型 DbWrappers 列表并延迟关闭我的泛型类型。
我将尝试在下面解释我为解决这个问题而研究过的策略,以及我到目前为止的实现
我自己的研究
在我看来,我可以为我的包装器创建一个非泛型基类并将它们保存为该基类,将解析原始泛型类型的责任委托给该基类,或者放弃我的包装器集合想法,转而使用我的服务构造函数上的特定参数(无聊 - 并且与我的复合启发实现不兼容)。
随着复合模式的流行,我想我不是第一个想要使用 DI 和 IoC 的具有“通用叶子”的复合模式解决方案的人。
我打算像这样使用我的fruitService:
myFruitService.GetDbMapper<MyFruitDto, DbEntityForThatSaidFruit(myOrange);
服务在它的 DbMapperCollection 中查找,找到具有提供的类型参数的映射器,并调用其 Save() 的实现;
到目前为止的实施
对于那些好奇的人,这是我的实现:
DbWrappers:
class SaveApplebWrapper : DbWrapper<TInput, TOutput>
// and plenty more wrapppers for any fruit imaginable
服务:
public abstract class DbMapperService : IDbMapperService
{
public IWrapperCollection Wrappers { get; set; }
protected BestandService(IWrapperCollection wrappers)
{
Wrappers = wrappers;
}
public DbWrapper<TInput, TResult> GetWrapper<TInput, TResult>()
{
return Wrappers.GetWrapper<TInput, TResult>();
}
}
我的 WrapperCollection 辅助类:
public struct WrapperKey
{
public static WrapperKey NewWrapperKey <TInput, TResult>()
{
return new WrapperKey { InputType = typeof(TInput), ResultType = typeof(TResult) };
}
public Type InputType { get; set; }
public Type ResultType { get; set; }
}
public struct WrapperContainer
{
public WrapperContainer(object wrapper) : this()
{
Wrapper= wrapper;
}
public object Wrapper{ get; set; }
public DbWrapper<TInput, TResult> GetWrapper<TInput, TResult>()
{
return Wrapper as DbWrapper<TInput, TResult>;
}
}
还有我的 WrapperCollection:
public class UcWrapperCollection : Dictionary<WrapperKey, WrapperContainer>,
IDbWrapperCollection
{
public void AddWrapper<TInput, TResult>(UcHandler<TInput, TResult> handler)
{
Add(WrapperKey.NewWrapperKey<TInput, TResult>(), new WrapperContainer(handler));
}
public DbWrapper<TInput, TResult> GetWrapper<TInput, TResult>()
{
var key = WrapperKey.NewWrapperKey<TInput, TResult>();
return this[key].GetWrapper<TInput, TResult>();
}
}
我在没有运气的情况下看过的问题
我看过的一些问题似乎与我的案例无关(尽管我的问题可能会通过通用委托解决,但我认为这不是解决我的问题的最佳解决方案。
- 使用 Autofac 注入通用类型参数
- Autofac。如何在构造函数中注入一个开放的 Generic Delegate
- 如何使用 Autofac 注入泛型工厂
- 具有嵌套开放泛型的 Autofac
【问题讨论】:
标签: c# generics dependency-injection autofac composite