自动映射器初始化为T类型

时间:2018-06-27 10:32:11

标签: c# entity-framework automapper

我想要一种通用方法来从数据库中获取数据并传递输出数据的外观模型。

我写了一个简单的方法:

public IEnumerable<T> GetUsers<T>()
{
    Mapper.Initialize(cfg =>
         cfg.CreateMap<IQueryable<User>, IQueryable<T>>());

    return OnConnect<IEnumerable<T>>(db =>
    {
        return db.Users.ProjectTo<T>().ToList();
    });
}

现在我希望我可以这样做:

var users = repo.GetUsers<UserViewModel>(); // it should be IEnumerable<UserViewModel>
var anotherUsers = repo.GetUsers<AnotherUserViewModel>(); // it should be IEnumerable<AnotherUserViewModel>

但是我无法再次重新初始化automapper。我应该怎么做才能使其正常工作?

2 个答案:

答案 0 :(得分:0)

  1. 仅在每次启动应用程序时初始化自动映射器
  2. 在设计代码时,您应该已经知道可以从User映射哪些类型,在这种情况下,您可以像这样在启动时注册所有类型:

        Mapper.Initialize(cfg => {
                cfg.CreateMap<User, UserDto1>();
                cfg.CreateMap<User, UserDto2>();
                ...
                cfg.CreateMap<User, UserDtoN>();
            });
    
  3. 即使您会实现它-尝试将User映射到Order也没有意义,但是您的建筑设计将为您提供这种可能性

  4. 如果您仍然想要这样做(如我在评论中所写),则可以为实例添加某种标记属性-MappableFrom(Type from),标记可在自动映射器范围内使用的所有DTO对象。然后在初始化应用程序时-扫描程序集以查找包含该属性的所有类型,然后在Automapper中注册。

答案 1 :(得分:0)

您可以使用个人资料来创建所有映射器,请点击此链接http://docs.automapper.org/en/stable/Configuration.html

您可以使用某种命名约定在静态构造函数中初始化所有想要的映射的另一种方法

在下面的代码中,我正在从相同的对象类型映射到相同的对象类型

// Data or View Models

public class AddressViewModel : BaseViewModel
{
    public string Address {get;set;}
    public AddressViewModel()
    {
        this.Address ="Address";
    }

}

public class UserViewModel : BaseViewModel
{
    public string Name {get;set;}
    public UserViewModel()
    {
        this.Name ="Name";
    }
}
public class BaseViewModel
{

}

存储库-在这里,我使用的视图模型应该在此处创建模型

public class CrudRepo
{
     public IEnumerable<T> GetData<T>() where T : class, new ()
     {
        var data = new List<T> { new T() };
        return AutoMapper.Mapper.Map<IEnumerable<T>>(data);
     }
}

然后在静态构造函数中初始化映射器

    static HelperClass()
    {
        // In this case all classes are present in the current assembly
        var items = Assembly.GetExecutingAssembly()
                            .GetTypes().Where(x =>
                                              typeof(BaseViewModel)
                                              .IsAssignableFrom(x))
                            .ToList();
        AutoMapper.Mapper.Initialize(cfg =>
        {
            items.ForEach(x =>
            {
                // Here use some naming convention or attribute to find out the Source and Destination Type
                //Or use a dictionary which gives you source and destination type
                cfg.CreateMap(x, x);
            });
        });
    }

现在您可以创建crud存储库的实例并获取映射项

    var userRepo = new CrudRepo();

    var users = userRepo.GetData<UserViewModel>();
    var address = addressRepo.GetData<AddressViewModel>();

Note:只要属性名称和类型相同,数据就会被映射,否则您必须创建ForMember