我有一个接口/类的映射层次结构,它使用由基类约束的泛型,我试图使用基类将它们解析为派生类。我想知道Autofac能否以比我目前更好的方式解决这个问题。
采用以下结构:
public interface IMapper<T1, T2>
where T1 : FooBase
where T2 : BarBase
{
T1 Map(T2 source);
}
public class FooBarMapper : IMapper<Foo, Bar>
{
public Foo Map(Bar source)
{
return new Foo
{
blahblah = source.xyz
};
}
}
接下来,我在“Foo”上有一个“To”扩展方法,它引用了基类型,但我想将它解析为正确的类型。我目前这样解决:
public static TDest To<TDest>(this BarBase o) where TDest : FooBase
{
var genericMapper = typeof(IMapper<,>).MakeGenericType(o.GetType(), typeof(TDest));
object mapper = IocProxy.Container.Resolve(genericMapper);
//... etc
}
这解决得很好......但是mapper只是一个对象。所以我必须使用反射来点击“地图”方法。我宁愿避免这样做。 autofac能否以更好的方式做到这一点,以便我最终得到一个IMapper而不是一个对象?例如,我更喜欢这样做,但autofac显然无法解决它:
var mapper = IocProxy.Container.Resolve<IMapper<FooBase, TDest>>();
答案 0 :(得分:0)
这个问题的答案有点难看。因为你无法创造&#34; To&#34;使用1泛型的扩展方法,你必须使代码看起来很丑,以便它可以推断出两种类型。像这样:
public static TDest To<TDest,TSource>(this TSource o) where TDest : new()
{
var mapper = IocProxy.Container.Resolve<IMapper<TSource, TDest>>();
return mapper.Map(o);
}
在更深处,我们得到了这个丑陋的电话:
var b = a.To<Bar,Foo>(); //<-- to convert it to "Bar" we need to specify both generics
是的,丑陋的!谁真的知道什么被映射到这里!除非你明确指明类型,否则你知道有些人现在已经走了多么疯狂。
无论如何,因为我不喜欢这样,我开发了一种解决方法来提高可读性。首先,我创建了一个Map类来包装我的对象(以及我的&#34; To&#34;函数)。这是一个额外的步骤,但作为一个很好的中介,帮助autofac正确解决泛型:
public class Map<TSource> where TSource : new()
{
public TSource Object { get; set; }
public Map(TSource o)
{
Object = o;
}
public TDest To<TDest>()
{
var mapper = IocProxy.Container.Resolve<IMapper<TSource, TDest>>();
return mapper.Map(Object);
}
}
然后使用稍微不同的通用扩展方法来获取Mapper(并将代码转换为我想要的样式):
public static Map<TDest> Map<TDest>(this TDest o) where TDest : new()
{
return new Map<TDest>(o);
}
这确实稍微改变了我想要的方式,但它同样也是如此。
所以不是这样:
foo.To<Bar, Foo>();
代码看起来像这样
foo.Map().To<Bar>()
你甚至可以进一步扩展它并添加和接口到Map类并让Autofac解决它,但我想这取决于你是如何自动编写映射器的。最后,性能提升可能微不足道。