【问题标题】:Service Layer Dependency Injection服务层依赖注入
【发布时间】:2016-11-29 15:05:03
【问题描述】:

我正在创建一个将调用服务层的 Web API,并且我正在尝试学习依赖注入(我希望使用 ninject),但我不确定如何创建对服务层的依赖。

这就是 web api 所调用的。

这里的问题是,当调用 IPersonService 时,该人将定义性别、名称、角色和种族。我正在使用构造函数注入,但不确定是应该调用 GenderService 还是应该调用业务层(在本例中由 Core 定义)。

我应该像上图还是下图那样调用服务

这就是我的个人服务的样子

namespace Service.Services
{
    public class PersonService : IPersonService
    {
        private IPersonCore personCore = null;
        private INameService nameService = null;
        private IRoleService roleService = null;
        private IGenderService genderService = null;
        private IEthnicityService ethnicityService = null;
        private IPrefixService prefixService = null;
        private Person currUser;

        public PersonService(IPersonCore _personcore, INameService _namecore, IRoleService _roleservice, IGenderService _genderservice, IEthnicityService _ethnicityservice, IPrefixService _prefixservice )
        {
            this.personCore = _personcore;
            this.nameService = _namecore;
            this.roleService = _roleservice;
            this.genderService = _genderservice;
            this.ethnicityService = _ethnicityservice;
            this.prefixService = _prefixservice;
        }

        public IEnumerable<Person> GetAllPerson()
        {
            if (isAuthorized())
            {
                return this.personCore.GetPersons();
            }
            return null;
        }

        public Person GetPersonByID(int id)
        {
            if (isAuthorized())
            {
                return this.personCore.GetPersonByID(id);
            }
            return null;
        }

        public Person GetPersonByEmail(string email)
        {
            if (isAuthorized())
            {
                return this.personCore.GetPersonByEmail(email);
            }
            return null;
        }

        public IEnumerable<Person> GetPersonByName(string first, string last, string middle)
        {
            if(isAuthorized())
            { 
                Name newname = this.nameService.CreateName(first, last, middle);
                return this.personCore.GetPersonByName(newname);
            }
            return null;
        }

        public IEnumerable<Person> GetPersonWithRoles(IEnumerable<Roles> r)
        {
        }

        public IEnumerable<Person> GetPersonWithDOB(DateTime d)
        {
            if (isAuthorized())
            {
                return this.personCore.GetPersonWithDOB(d);
            }
            return null;
        }

        public Person SetPersonRole(int id, Roles r)
        {
        }

        public Person SetGender(int id, Gender g)
        {
        }

        public Person SetEthnicity(int id, Ethnicity e)
        {
        }

        public Person SetPrefix(int id, Prefix p)
        {
        }

        public Person CreatePerson(Person p)
        {
            if (isAuthorized())
            {
                return personCore.AddPerson(p);
            }
            return null;
        }

        public Person UpdatePerson(Person p)
        {
            if (isAuthorized())
            {
                return personCore.UpdatePerson(p);
            }
            return null;
        }

        public Person ActivatePerson(int id)
        {
            if (isAuthorized())
            {
                return personCore.ActivatePerson(id);
            }
            return null;
        }

        public Person DeactivatePerson(int id)
        {
            if (isAuthorized())
            {
                return personCore.DeactivatePerson(id);
            }
            return null;
        }

        public bool DeletePerson(int id)
        {
            if (isAuthorized())
            {
                return personCore.DeletePerson(id);
            }
            return false;
        }

        protected bool isAuthorized()
        {
            //Probably move to common
            return true;
        }
    }
}

当我从 Web API 调用它时,我的问题是,它听起来像是很多依赖来查找有关某个人的信息。

【问题讨论】:

    标签: c# ninject ioc-container


    【解决方案1】:

    您可以通过 2 种方式简化此过程:

    1. 您的 PersonService 看起来并不依赖于 Role、Gender、Ethnicity 和 Prefix 服务,因为您不会从其方法中调用它们。它是您的客户端代码调用的外壳,而不是直接调用这些服务本身。如果是这种情况,那么您可以通过消除这 4 个依赖项来简化您的 PersonService:

      private IRoleService roleService = null;
      private IGenderService genderService = null;
      private IEthnicityService ethnicityService = null;
      private IPrefixService prefixService = null;
      

      并将这些方法输出到各自的服务中:

      public Person SetPersonRole(int id, Roles r)
      {
      }
      public Person SetGender(int id, Gender g)
      {
      }
      public Person SetEthnicity(int id, Ethnicity e)
      {
      }
      public Person SetPrefix(int id, Prefix p)
      {
      }
      
    2. 如果您绝对需要将这些方法保留在 IPersonService 中,那么您将在方法中而不是在构造函数中注入依赖项。

      关于对服务或核心的依赖,这取决于你的服务做什么。如果你的服务只是调用核心,那么你自己去核心。如果您的 Service 正在执行某些验证或其他任何操作,您可能希望依赖它来避免在 PersonService 中复制相同的代码。

    【讨论】:

      【解决方案2】:

      PersonService 类包含许多依赖项,因为您违反了Single Responsibility Principle。这个类有很多职责,每次你添加一个新特性时你最终都会改变这个类(这是一个Open/Closed Principle违规)。此外,isAuthorized 方法是一个横切关注点,这个类应该没有这个概念。

      最重要的是,您将当前登录的用户注入PersonService。这是运行时数据,constructing application components using runtime data is an anti-pattern

      有很多方法可以解决这个问题,但一切都归结为理解 SOLID 原则。然而,这样做可能是一项艰巨的任务,特别是如果您刚刚开始使用 DI 和软件设计。您可以阅读很多关于此的书籍,例如 Robert C. Martin 的 the amazing work 以及 Mark Seemann 的 Dependency Injection in .NET 等有关依赖注入的书籍。

      过去几年帮助我很多的设计是基于消息的架构,其中用例由消息描述,实现由通用抽象描述(阅读thisthis)。事实证明,这些设计非常灵活且可维护,因为它们允许透明地添加横切关注点,并允许在不更改任何现有代码的情况下添加新功能。这样的设计还允许将您的 Web API 层减少为一个简单的基础设施,在添加新功能时不需要更改。你可以阅读这个概念here(注意:那篇文章是关于 WCF,但 Web API 的概念是相同的),here 是一个 Github 存储库,它展示了如何在 WCF 和 Web API 中实现这一点。

      祝您在掌握软件的道路上一切顺利。

      【讨论】:

      • 谢谢,所以从用户的角度来看,Personservice 应该返回基本的像 id、password、email 但角色,genders 应该只给genderService,并且两个服务不应该对话彼此?
      • @Jseb:这不是我要宣传的。我正在推广的是一个模型,其中每个查询(例如GetAllPersonGetPersonByEmail)都包含在它自己的类中。这样的类可以依赖于它所需要的,但在大多数情况下只会使用DbContext 来查询数据库。
      猜你喜欢
      • 2017-09-26
      • 2014-02-25
      • 2020-05-01
      • 1970-01-01
      • 2020-09-09
      • 1970-01-01
      • 2020-01-17
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多