0

首先,我已经在网上搜索了一个解决方案,找不到任何东西。

我正在研究一个高度解耦的解决方案,所有类都是为 DI 方法设计的(当然要求接口作为依赖项)。我们在 MVC 层中使用 Automapper 来转换扁平化 ViewModel 中的服务器端 POCO。到目前为止没有什么奇怪的。

复杂性在于 ViewModel 的某些属性必须使用在 IoC 容器 (ninject) 中注册的某些服务来创建,并且在配置自动映射器的应用程序启动期间不可用。告诉 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.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接口的不同方法来解决。为了弄清楚事实:

  • 我不能在配置 automapper 的地方使用 DI,因为它发生在 Application_Start (或应用程序启动调用的某些静态方法)
  • 即使可能,我也不会在应用程序级别解析我的IUrlResolver ,因为它在所有应用程序生命周期中都是陈旧的
  • 如果我对单个属性使用 ValueResolver,一切都很好。ValueResolver 构造函数请求IUrlResolver,它会在发生自动映射器转换时在运行时注入。
  • 我可以为我的 20 个属性创建 20 个不同的 ValueResolver 类,但它会使代码变得混乱,产生大量的代码重复,没有可重用性等。一堆糟糕的做法。
  • 我想要的是能够使用自定义类(如 TypeConverter)部分映射对象,同时使用默认约定引擎映射所有其他属性

我没有要发布的“示例语法”,因为我尝试过的最接近的方法是我之前发布的方法。如果存在,我愿意接受完全不同的方法,只要它允许我保持事物解耦并且不涉及在单独的类中重构这些属性。

4

1 回答 1

0

我不能在配置 automapper 的地方使用 DI,因为它发生在 Application_Start (或应用程序启动调用的某些静态方法)

这听起来像是一个相当人为的约束。DI 容器连接和 AutoMapper 配置都可能发生在应用程序启动阶段的早期。在配置 DI 容器后运行 AutoMapper 配置至少在理论上应该是可行的。如果有实际原因导致情况并非如此,您能否详细说明?

附录: 如果核心问题是您希望在映射时启用 IoC 容器的依赖关系解析,AutoMapper 确实为此提供了挂钩。有关您可以使用的两种候选方法,请参阅https://github.com/AutoMapper/AutoMapper/wiki/Custom-value-resolvers#custom-constructor-methodshttps://github.com/AutoMapper/AutoMapper/wiki/Containers .

于 2013-03-19T16:51:27.807 回答