【问题标题】:How can I create a List<Customer> by Dependency Injection? [duplicate]如何通过依赖注入创建 List<Customer>? [复制]
【发布时间】:2013-12-24 17:09:10
【问题描述】:

我的目标是从数据库加载数据并返回一个 List 。以下是我当前的代码:

    public class CustomerRepository : ICustomerRepository
     {

        public IEnumerable<Customer> GetAll()
        {
            List<Customer> Customers = new List<Customer>();

            DataTable dtResult; 
            using (
        DbCommand cmd = TheDB.GetStoredProcCommand("spSelectAllCustomer"))
            {
                dtResult = TheDB.ExecuteDataSet(cmd).Tables[0];
            }


            Customers.AddRange( 
               from DataRow row in dtResult.Rows

               //*** How can I inject a new Customer instance in here?

               select new Customer() {
                          Name = row[0].ToString(), 
                          Email = row[1].ToString()
                     });

            return Customers;
        }
    }

我不知道如何用注入替换新客户。 我应该使用 container.Resolve 吗? container.Resolve 是服务定位器,是反模式吗?

谢谢。

【问题讨论】:

    标签: c# dependencies unity-container code-injection


    【解决方案1】:

    使用Factory Pattern 创建您的实例。我会重构你的代码如下。

    引入一项服务,该服务将调用 Repo 和您创建的工厂。该服务,我称为 ICustomerProcessor。 (ICusomerService 在这里可能不是正确的选择)。这个处理器,你的工厂和存储库是依赖注入的,使用你的 IUnityContainer。有些人确实将其称为Facade

    public interface ICustomerProcessor {
        IEnumerable<Customer> GetAll();
    }
    

    此服务的实现将简单地调用存储库来获取数据,并调用工厂来创建实体。

    public class CustomerProcessor : ICustomerProcessor {
        private readonly ICustomerFactory _customerFactory;
        private readonly ICustomerRepository _customerRepository;
    
        public CustomerProcessor(ICustomerRepository customerRepository, ICustomerFactory customerFactory)
        {
            _customerRepository = customerRepository;
            _customerFactory = customerFactory;
        }
    
        public IEnumerable<Customer> GetAll()
        {
            var data = _customerRepository.GetDataTable();
            return _customerFactory.CreateCustomers(data);
        }
    }  
    

    repository 只是你的数据库的一个表示,它只是抽象你的 db 调用。

    public class CustomerRepository : ICustomerRepository
    {
        private readonly IDatabaseContext _database;
    
        public CustomerRepository(IDatabaseContext database) {
            _database = database;
        }
    
    
        public DataTable GetDataTable() {
            DataTable dtResult;
            using (DbCommand cmd = _database.GetStoredProcCommand("spSelectAllCustomer"))
            {
                dtResult = _database.ExecuteDataSet(cmd).Tables[0];
            }
    
            return dtResult;
        }
    }
    

    请注意,IDatabaseContext 不需要依赖注入,它可以只是一个静态上下文,您称之为 db。但关键思想是您的存储库封装了数据库操作,仅此而已。

    关于 Container.Resolve : 你不需要这个,因为你的服务是通过 contructore injection 注入的。您的域对象不应该被依赖注入。它们只是实体。

    关于服务定位器。 service locator 不是反模式,而是人们使用它的方式使其成为反模式。在您的情况下,绝对不需要在上下文中使用服务定位器。但在某些情况下,当您无法掌握某些依赖项时,您可能会使用服务定位器。但这些情况很少见。

    更新:

    ICustomerFactory的实现:

    public interface ICustomerFactory {
        IEnumerable<Customer> CreateCustomers(DataTable data);
    }
    
    public class CustomerFactory
    {
        public IEnumerable<Customer> CreateCustomers(DataTable data)
        {
             return (from DataRow row in data.Rows
                 select new Customer
                 {
                     Name = row[0].ToString(), Email = row[1].ToString()
                 }).ToList();
        }
    }
    

    【讨论】:

    • 您能否演示一下如何实现 CusotmerFactory.CreateCustomers(data)?我认为我仍然必须使用“new Customer()”在工厂中创建客户。谢谢你。
    • @user3026964 我已经更新了我的答案以包括 ICustomerFactory 的实现。还请记住,正如您所说,您需要“new Customer()”,但它已从工厂中抽象出来。这很好,因为您将这种担忧与回购本身分离。
    • Valve1900:感谢您的快速回复。这种方式增加了一个新的工厂类,作为单一责任原则应该是一件好事。但现在耦合已移至 CustomerFactory 类。或者,可以与实体对象耦合。域实体的多个实现可能是不正常的。没必要有ICusotmer接口注入工厂吧?
    • Valve1900:我想知道我是否有不同的 ICustomer 实现,例如我必须为不同的客户构建多个网站。客户类别将包括针对每个客户的不同业务规则。在这种情况下如何实现工厂?我应该创建多个ICustomerFactory,以便每个工厂分别创建一个类型的Customer?仍然在每个工厂类中,我可以使用“new AnotherCustoemr()”来创建 IEnumerable 实例?
    • 如果你读过工厂模式,你就会明白使用工厂类创建实体是完全没问题的。 “CustomerFactory”只是一个例子,但你可以调用任何你想要的。您不需要多个工厂。这是矫枉过正。像 ApplicationEntityFactory 之类的东西,它会更通用,您也可以使用这个工厂来创建不是客户的实体。顺便说一句,SO 中已经回答了类似的问题,因此您可以更了解这种模式。
    猜你喜欢
    • 2010-12-14
    • 2020-01-02
    • 2011-07-10
    • 1970-01-01
    • 2019-12-03
    • 1970-01-01
    • 2017-09-04
    • 2013-12-25
    • 1970-01-01
    相关资源
    最近更新 更多