Generics 使用AutoMapper实现.ToViewModel()

Generics 使用AutoMapper实现.ToViewModel(),generics,automapper,Generics,Automapper,我试图通过实现扩展方法.ToViewModel()来简化AutoMapper在我的项目中的使用。基本上,它只是标准调用的包装器,但我经常发现自己对每次要映射某个内容时必须键入的内容感到恼火。比较两者: var viewModel = Mapper.Map<DomainEntityType, ViewModelType>(entity); // or... var viewModel = entity.ToViewModel(); 然而,我无法让它飞起来 下面的NUnit测试尝试测试

我试图通过实现扩展方法
.ToViewModel()
来简化AutoMapper在我的项目中的使用。基本上,它只是标准调用的包装器,但我经常发现自己对每次要映射某个内容时必须键入的内容感到恼火。比较两者:

var viewModel = Mapper.Map<DomainEntityType, ViewModelType>(entity);
// or...
var viewModel = entity.ToViewModel();
然而,我无法让它飞起来

下面的NUnit测试尝试测试这一点(尽管我不确定
Assert.AreEqual
是否真的测试了我想要的-它是否需要引用相等?如果是,我如何测试“是等效的”?)。测试失败,并显示消息

Expected: <Castle.Proxies.IViewModel`1Proxy> But was: <Castle.Proxies.IViewModel`1Proxy> 应为:<Castle.Proxies.IViewModel`1Proxy> 但是:
[测试]
public void domainentitypemapsviewmodeltype()
{
var entity=new DomainEntityType();
var oldskool=Mapper.Map(实体);
var extension=inspectionObject.ToViewModel();
AreEqual(oldskool,扩展名);
}

除了我的测试可能测试错误之外,我是否遗漏了AutoMapper如何工作的一些基本信息?AutoMapper是否能够将某些内容正确映射到接口?(我确实有一个类,
EntityViewModel
,它实现了
ViewModel
,但我还没有具体告诉AutoMapper…)

我最终以一种通用的方式做到了这一点。它需要对我的对象进行一些调整,但我做了以下几点:

从以前开始,我的大多数实体都继承自
实体
(通常是
实体
,但id可能是另一种数据类型,例如GUID),它反过来实现了接口
属性
(使用单个属性
公共TId id{get;}
)。不继承
实体
的少数实体至少实现了
属性

我创建了一个新类,它覆盖
Equals
GetHashcode

public class ViewModel<TEntity, TId> : IEntity<TId>
    where TEntity : IEntity<TId>
{
    public TId ID { get; set; }

    public override bool Equals(object obj)
    {
        var viewModel = obj as ViewModel<TEntity, TId>;
        return viewModel != null && Equals(viewModel);
    }

    public bool Equals(ViewModel<TEntity, TId> other)
    {
        return ID.Equals(other.ID);
    }

    public override int GetHashCode()
    {
        // Not only returning ID.GetHashCode() in case I want to add more
        // properties later...
        var hash = 7;
        hash = (hash * 17) + ID.GetHashCode();

        return hash;
    }
}
我非常满意,因为我最初的目标是从控制器的实现中抽象出AutoMapper,这已经很好地实现了


您会注意到,IEntity也有一个非泛型版本——这只是一个空接口,
IEntity
继承自。这可能会被认为很枯燥,但不使用泛型版本有一个简单的原因:如果使用泛型版本,还必须将其指定为扩展方法的类型参数。您将使用
entity.To()
而不是上面的语法,因为推断类型参数是全有或全无的事情。

您能尝试将泛型类型参数约束更改为where tenty:entity吗?顺便说一句,您是否尝试在调试器中查看两个对象是否与预期的相同?同时尝试将Assert.AreEqual更改为Assert.Areame,它将检查两个对象是否引用了同一个对象实例我也想知道如何实现这一点…@Baldy:我解决了这个问题-请查看我对这个问题的答案。谢谢提醒,我将尝试:)
[Test]
public void DomainEntityTypeMapsViewModelType()
{
    var entity = new DomainEntityType();
    var oldskool = Mapper.Map<DomainEntityType, IViewModel<Entity>>(entity);
    var extension = inspectionObject.ToViewModel();

    Assert.AreEqual(oldskool, extension);
}
public class ViewModel<TEntity, TId> : IEntity<TId>
    where TEntity : IEntity<TId>
{
    public TId ID { get; set; }

    public override bool Equals(object obj)
    {
        var viewModel = obj as ViewModel<TEntity, TId>;
        return viewModel != null && Equals(viewModel);
    }

    public bool Equals(ViewModel<TEntity, TId> other)
    {
        return ID.Equals(other.ID);
    }

    public override int GetHashCode()
    {
        // Not only returning ID.GetHashCode() in case I want to add more
        // properties later...
        var hash = 7;
        hash = (hash * 17) + ID.GetHashCode();

        return hash;
    }
}
public class EntityViewModel : ViewModel<EntityType, int>
{
    // data properties
}
public static TViewModel To<TViewModel>(this IEntity entity) where TViewModel : class
{
    return Mapper.Map(entity, entity.GetType(), typeof(TViewModel)) as TViewModel;
}

public static TEntity ToEntity<TEntity, TId>(this ViewModel<TEntity, TId> viewmodel) where TEntity : class, IEntity<TId>
{
    return Mapper.Map(viewmodel, viewmodel.GetType(), typeof(TEntity)) as TEntity;
}
var entity = new EntityType();
var viewmodel = entity.To<EntityViewModel>();

var backagain = viewmodel.ToEntity();