【问题标题】:Abstract Automapper Projections抽象 Automapper 投影
【发布时间】:2016-03-05 18:31:00
【问题描述】:

我使用 Entity Framework 6 开发 web api 应用程序。 我想集成并开始使用 Automapper 来映射到我的 EF 实体模型。

我已经阅读了有关投影的内容,并意识到如果我决定使用 Automapper,则有必要使用 Project().To 以获得更好的性能。但是,我不想将我的 DAL 暴露给 Automapper 库。

有没有办法可以抽象出 Automapper Project()?

提前致谢

【问题讨论】:

  • 我强烈建议不要使用这些图层规则。间接只是引入了复杂性,并没有太多好处。

标签: c# entity-framework automapper abstraction


【解决方案1】:
  1. 使用“投影”方法创建界面,可以复制 原始 AutoMapper 方法。
  2. 然后创建一个具体的实现。
  3. 然后将此接口添加到存储库的构造函数中。
  4. 使用它
  5. 将接口注册到您的依赖注入容器。
  6. 按 F5

这是一个完整的例子
(当然,您将在正确的层中拥有每个类/接口)。

using AutoMapper;
using AutoMapper.QueryableExtensions;
using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
using System.Linq.Expressions;

namespace ConsoleApplicationMapper
{
    class Program
    {
        static void Main(string[] args)
        {
            Mapper.Initialize(c =>
            {
                c.CreateMap<Customer, CustomerModel>();
            });

            //If you use a dependency injection container you don't have to use the constructors
            var repository = new CustomerRepository(new EntityProjector());

            foreach (var item in repository.GetCustomers())
            {
                Console.WriteLine(item.Name);
            }

            Console.ReadLine();
        }
    }

    public class CustomerModel
    {
        public int CustomerId { get; set; }
        public string Name { get; set; }
    }

    public interface IEntityProjector
    {
        IQueryable<TDestination> ProjectTo<TDestination>(IQueryable source, params Expression<Func<TDestination, object>>[] membersToExpand);
    }

    public class EntityProjector : IEntityProjector
    {
        public IQueryable<TDestination> ProjectTo<TDestination>(IQueryable source, params Expression<Func<TDestination, object>>[] membersToExpand)
        {
            return source.ProjectTo(membersToExpand);
        }
    }

    public interface ICustomerRepository
    {
        IEnumerable<CustomerModel> GetCustomers();
    }

    public class CustomerRepository : ICustomerRepository
    {
        private readonly IEntityProjector projector;
        public CustomerRepository(IEntityProjector theProjector)
        {
            projector = theProjector;
        }
        public IEnumerable<CustomerModel> GetCustomers()
        {
            MyContext context = new MyContext();

            //Uncomment this if you want to confirm that only CustomerId,Name are selected and not LastName
            //context.Database.Log = s => Console.WriteLine(s);

            return context.Customers.SelectTo<CustomerModel>();
        }
    }

    public class Customer
    {
        public int CustomerId { get; set; }
        public string Name { get; set; }
        public string LastName { get; set; }
    }


    public class MyContext : DbContext
    {
        public DbSet<Customer> Customers { get; set; }
    }

    public static class MyExtentions
    {
        static IEntityProjector projector;
        static MyExtentions()
        {
            //You can get it from your dependecy injection container if you use one
            projector = new EntityProjector();
        }
        //I renamed this SelectTo instead of ProjectTo so you don't have any conflict if you use AutoMapper
        //Change it to to ProjectTo if you want
        public static IQueryable<TDestination> SelectTo<TDestination>(this IQueryable source, params Expression<Func<TDestination, object>>[] membersToExpand)
        {
            return projector.ProjectTo<TDestination>(source);
        }
    }
}

【讨论】:

  • 您是否愿意完全完成您的示例,包括您最后提到的可能的扩展方法?我不认为我知道如何自己实现它。无论如何,非常感谢你
  • @S.Peter Updated。如果您有任何问题,请告诉我
  • 当然,现在你可以删除你仓库的构造器和私有字段。我只是把它留在那里,以防你不想使用扩展方法
  • 扩展类必须是静态的吧?我可以注入静态类吗?以前从未尝试过
  • 不幸的是你需要一个静态类。这很棘手。查看相关问题stackoverflow.com/questions/14894980/…stackoverflow.com/questions/1293489/…
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多