我正在开发一个使用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;
}
}
它在一个地方给了我所需的所有逻辑,我可以在任何地方使用它。如果我需要更新代码,它与模型定义相同。那我错过了什么?
答案 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);
}
这描述了具有两种输入类型TSource
和TResult
的通用接口,后者具有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
}
}
无论您做什么,都要抵制为此定义静态方法的冲动。选择构造函数或映射器。