自动apper继承和自定义类型转换器
本文关键字:类型 类型转换 转换器 自定义 apper 继承 自动 | 更新日期: 2023-09-27 18:04:53
首先,我已经在网上和SO中搜索了一个解决方案,没有找到任何东西。
我正在研究一个高度解耦的解决方案,所有的类都是为DI方法设计的(当然要求接口作为依赖项)。我们在MVC层中使用Automapper来转换平面化ViewModels中的服务器端poco。到目前为止没有什么奇怪的。
复杂性是由于ViewModels的一些属性必须使用在IoC容器(ninject)中注册的一些服务来创建,并且在应用程序启动(配置automapper的地方)期间不可用。告诉automapper使用什么方法来解析类型很容易,只需按照文档中的一行配置即可。
对于简单的情况,当单个属性需要这种行为时,我们为该属性创建一个自定义的ValueResolver,在构造函数中公开依赖关系,并使用它们来返回所需的值。
当我们有20个属性需要相同的行为,但不同的输出值时,问题就出现了,而所有其他ViewModel属性都可以使用默认的"自动映射"。
我找不到一种方法来告诉automapper"解析这些属性,使用这个类,其他的使用你的约定"。
我尝试了几种方法,包括将所需的属性放在接口上,然后使用wiki上描述的继承映射。只要我不使用TypeConverter,它就可以工作,因为我需要它(或类似的东西)通过DI/IoC获得所需的服务。
一个例子:
public interface IMyInterface
{
string MyUrl1 {get;set;}
//snip with many other urls
}
public class MyViewModel : IMyInterface
{
public string MyUrl1 {get;set;}
//snip with many other urls
public string MyAutomapperProperty1 {get;set;}
//snip with many other properties where I want to use the conventions
}
我需要的是这样的东西
public class MyTypeConverter : TypeConverter<MyPoco, IMyInterface>
{
// here in the overridden method return an instance of MyViewModel
// with just the properties exposed by the interface
}
然后在automapper config中:
Automapper.CreateMap<MyPoco, IMyInterface>()
.Include<MyPoco, MyViewModel>()
.ConvertUsing<MyTypeConverter>();
Automapper.CreateMap<MyPoco, MyViewModel>();
这行不通。如果我删除对ConvertUsing的调用,并使用ForMember方法添加内联映射,一切都会正常工作,并且ForMember声明被第二个映射正确继承,而不是ConvertUsing。但是我不能使用ForMember方法进行DI(因为我在应用程序开始时,这是静态的,而且这意味着在应用程序级别实例化这些对象并使它们在所有应用程序中保持活动,而不是在需要时创建和处置它们)。
我知道一个解决方案是将相关属性放在一个单独的对象中,并直接为该对象创建一个TypeConverter并使用它,但是重构这些poco现在不是一个选择,此外,似乎很奇怪没有办法使继承和DI一起工作。
希望有人能帮助我,谢谢阅读。
按照要求,我会尽量更清楚地说明我想要达到的目标。
我们有一些"服务",只能通过它们的接口在应用程序级别上知道。比如:
public interface IUrlResolver { }
它暴露了一些方法来获取与我们的应用程序相关的url,基于我们传递的一些参数和其他东西。实现也可以将依赖项公开给其他服务(接口)等等。因此,我们使用DI,让IoC容器解析依赖链。
现在让我们假设我的ViewModel有50个属性,其中30个可以与automapper的基于约定的映射一起使用,而其他20个需要通过我的IUrlResolver接口的不同方法来解决。为了弄清事实:- 我不能有DI,我配置automapper,因为它发生在Application_Start(或应用程序启动调用的一些静态方法) 我不会在应用程序级别解析我的IUrlResolver,即使它是可能的,因为它将在整个应用程序生命周期失效
- 如果我使用ValueResolver单个属性,一切都很好。ValueResolver构造函数请求IUrlResolver,它在运行时自动转换发生时被注入。
- 我可以为我的20个属性创建20个不同的ValueResolver类,但它使代码混乱,获得大量的代码重复,没有可重用性等。一堆糟糕的做法。
- 我想要的是部分映射对象与自定义类(如TypeConverter)的能力,而所有其他属性被映射与默认约定引擎
我没有一个"示例语法"张贴,因为我尝试过的最接近的方式是我之前发布的。如果有完全不同的方法,只要它允许我保持事物的解耦,并且不需要在单独的类中重构这些属性,我愿意采用这种方法。
我不能在配置automapper的地方使用DI,因为它发生在Application_Start(或应用程序start调用的静态方法)
这听起来像是一个相当人为的约束。DI容器连接和AutoMapper配置都可能发生在应用程序启动阶段的早期。在配置了DI容器之后运行AutoMapper配置至少在理论上是可行的。如果有实际的原因,请详细说明。
附录:如果核心问题是希望在映射时解析来自IoC容器的依赖项,那么AutoMapper确实为此提供了挂钩。请参阅https://github.com/AutoMapper/AutoMapper/wiki/Custom-value-resolvers#custom-constructor-methods和https://github.com/AutoMapper/AutoMapper/wiki/Containers了解可以使用的两种候选方法。