C# 抽象自动映射

C# 抽象自动映射,c#,entity-framework,automapper,abstraction,C#,Entity Framework,Automapper,Abstraction,我使用实体框架6开发web api应用程序。 我想集成并开始使用Automapper来映射我的EF entites模型 我已经阅读了有关投影的内容,并意识到如果我决定使用Automapper,有必要使用Project(),以获得更好的性能。但是,我不想将我的DAL公开给Automapper库 有没有办法把Automapper项目()抽象出来 提前谢谢 使用“投影”方法创建一个界面,可以复制 原始自动映射方法 然后创建一个具体的实现 之后,将此接口添加到存储库的构造函数中 使用它 将接口注册到依赖

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

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

有没有办法把Automapper项目()抽象出来

提前谢谢

  • 使用“投影”方法创建一个界面,可以复制 原始自动映射方法
  • 然后创建一个具体的实现
  • 之后,将此接口添加到存储库的构造函数中
  • 使用它
  • 将接口注册到依赖项注入容器
  • 按F5
  • 下面是一个完整的示例
    (当然,每个类/接口都位于正确的层中)

    使用AutoMapper;
    使用AutoMapper.QueryableExtensions;
    使用制度;
    使用System.Collections.Generic;
    使用System.Data.Entity;
    使用System.Linq;
    使用System.Linq.Expressions;
    命名空间控制台应用程序映射器
    {
    班级计划
    {
    静态void Main(字符串[]参数)
    {
    初始化映射器(c=>
    {
    c、 CreateMap();
    });
    //如果使用依赖项注入容器,则不必使用构造函数
    var repository=new CustomerRepository(new EntityProjector());
    foreach(repository.GetCustomers()中的var项)
    {
    Console.WriteLine(项目名称);
    }
    Console.ReadLine();
    }
    }
    公共类CustomerModel
    {
    public int CustomerId{get;set;}
    公共字符串名称{get;set;}
    }
    公共接口IEntityProjector
    {
    IQueryable ProjectTo(IQueryable源,参数表达式[]membersToExpand);
    }
    公共类EntityProjector:IEntityProjector
    {
    公共IQueryable项目到(IQueryable源,参数表达式[]成员扩展)
    {
    返回source.ProjectTo(membersToExpand);
    }
    }
    公共接口ICCustomerRepository
    {
    IEnumerable GetCustomers();
    }
    公共类CustomerRepository:ICCustomerRepository
    {
    私人只读IEntityProjector投影仪;
    公共客户存储库(客户项目或项目)
    {
    投影仪=投影仪;
    }
    公共IEnumerable GetCustomers()
    {
    MyContext上下文=新的MyContext();
    //如果要确认只选择CustomerId、Name而不选择LastName,请取消对此的注释
    //context.Database.Log=s=>Console.WriteLine;
    返回context.Customers.SelectTo();
    }
    }
    公共类客户
    {
    public int CustomerId{get;set;}
    公共字符串名称{get;set;}
    公共字符串LastName{get;set;}
    }
    公共类MyContext:DbContext
    {
    公共数据库集客户{get;set;}
    }
    公共静态类MyExtensions
    {
    静态投影投影仪;
    静态MyExtensions()
    {
    //如果您使用dependecy注射容器,则可以从容器中获取
    投影仪=新的EntityProjector();
    }
    //我将此SelectTo重命名为而不是ProjectTo,这样在使用AutoMapper时就不会有任何冲突
    //如果需要,请将其更改为ProjectTo
    公共静态IQueryable SelectTo(此IQueryable源,参数表达式[]membersToExpand)
    {
    将投影仪返回到(源);
    }
    }
    }
    
    您是否愿意完整地完成您的示例,包括您在最后提到的可能的扩展方法?我想我自己不知道如何实施它。不管怎样,非常感谢much@S.Peter更新。如果您有任何问题,请告诉我。现在您可以删除存储库的构造函数和私有字段。我只是将其保留在那里,以防您不想使用扩展方法扩展类必须是静态的,对吗?我可以注入到静态类中吗?以前从未尝试过。不幸的是,您需要一个静态类。这很棘手。请参阅相关问题,我强烈建议不要使用这些层规则。间接只是引入了复杂性,没有多少好处。
    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);
            }
        }
    }