Mapper与构造函数

时间:2016-07-05 18:24:51

标签: c# automapper

我正在开发一个使用AutoMapper设置的项目。由于大部分内容对我而言都是陌生的,所以我对此持开放态度。

假设我有两个班级:

function order(words){
  words = words.split(" ").sort(function(a,b){
    return a.match(/\d/) -  b.match(/\d/) // get first digit and compare them
  })
 console.log(words);
}

而不是使用ORM,为什么我不会只使用一个以FooView作为参数的构造函数。

class Foo
{
    public string name { get; set; }
    public int rank { get; set; }
    public bool isDelected { get; set; }
}

class FooView
{
    public string name { get; set; }
    public int rank { get; set; }
}

在这种情况下,每当我有一个FooView并且我需要Foo时,我只是说

class Foo
{
    public Foo(FooView source)
    {
        this.name = source.name;
        this.rank = source.rank;
    }
}

它在一个地方给了我所需的所有逻辑,我可以在任何地方使用它。如果我需要更新代码,它与模型定义相同。那我错过了什么?

2 个答案:

答案 0 :(得分:2)

如果您的所有模型都在同一个程序集中或者直接依赖于其他项目,那么这可能没问题。如果您的模型很好地对齐,AutoMapper非常棒,但是如果您需要对映射进行更多控制,我倾向于将它们放在专用帮助器或MVC控制器中的静态映射方法中。

这有助于使我的映射逻辑与模型分开

private static Foo MapToFoo(FooView vm) 
{
    var foo = new Foo();
    foo.Name = vm.Name;
    foo.Rank = vm.Rank;
    ...
    return foo;
}

答案 1 :(得分:0)

通常,我喜欢您遵循的模式。即使它使我有些异端,我还是希望手动映射所有内容。例如,数据库pocos并进一步转换数据库pocos以查看模型。是的,您可以对某些具有大量属性的类进行争论。但这也许是代码气味?

如果您的项目恰好具有大量具有20-30个属性的合法类,那么您也许应该休息一下,自学PowerShell,然后开始生成映射。

那为什么要经历所有这些努力呢?很简单,反射很昂贵而且很烂。它喜欢资源,即使在中等规模扩展时,无论您进行了什么缓存等努力,都可以确保使代码变慢。调试也更加困难。

我只是不喜欢将决策(可能是代码中最脆弱的部分)移交给运行时。

现在来看构造函数与映射器的争论。对于一个小型项目,我认为构造函数将完美运行。很容易理解和测试。随着项目的发展,映射器变得不错,因为它们允许使用separation of concerns。但是像往常一样,不要立即接触图书馆,请想一想您遇到的问题,然后尝试用代码解决。

在我们的案例中,我们希望将一件事投射到另一件事中,因此让我们为此定义一个简单的接口:

public interface IMapper<in TSource, in TResult>
    where TResult : new() {
        void Map(TSource source, TResult result);
}

这描述了具有两种输入类型TSourceTResult的通用接口,后者具有new()约束,因此我们可以以编程方式制造它。

现在让我们添加一些功能,以一对一,一对一的null和多对多的映射:

public static class IMapperExtensions {
    public static TResult Map<TSource, TResult>(this IMapper<TSource, TResult> mapper, TSource source)
        where TResult : new() {
        TResult result = new TResult();

        mapper.Map(source, result);

        return result;
    }

    public static TResult MapAllowNull<TSource, TResult>(this IMapper<TSource, TResult> mapper, TSource source)
        where TResult : new() {
        if (source == null) {
            return default(TResult);
        }

        return mapper.Map(source);
    }

    public static IEnumerable<TResult> MapCollection<TSource, TResult>(this IMapper<TSource, TResult> mapper, IEnumerable<TSource> source)
        where TResult : new() {
        if (source == null) {
            yield return default(TResult);
        }
        else {
            foreach (var s in source) {
                yield return mapper.Map(s);
            }
        }
    }
}

一个实现:

class Foo {
    public string name { get; set; }
    public int rank { get; set; }
    public bool isDelected { get; set; }
}

class FooView {
    public string name { get; set; }
    public int rank { get; set; }
}

class FooToFooView : IMapper<Foo, FooView> {
    public void Map(Foo source, FooView result) {
        result.name = source.name;
        result.rank = source.rank
    }
}
  

无论您做什么,都要抵制为此定义静态方法的冲动。选择构造函数或映射器。