服务层依赖注入

Service Layer Dependency Injection

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

这就是网络 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 我的问题是,它听起来像是在寻找关于某个人的某些东西的很多依赖性。

PersonService class 包含很多依赖项,因为你违反了 Single Responsibility Principle. This class has many responsibilities and you'll end up changing this class every time you are adding a new feature (which is a Open/Closed Principle 违规)。此外,isAuthorized方法是一个横切关注点,这个class应该没有概念。

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

有很多方法可以解决这个问题,但这一切都归结为理解 SOLID 原则。然而,这样做可能是一项艰巨的任务,尤其是当您刚刚开始 DI 和软件设计时。您可以阅读很多关于此的书籍,例如 the amazing work from Robert C. Martin and books about Dependency Injection like Mark Seemann's Dependency Injection in .NET.

过去几年对我帮助很大的设计是基于消息的架构,其中用例由消息描述,实现由通用抽象描述(阅读 this and this). These designs have proven to be very flexible and maintainable, since they allow adding cross-cutting concerns transparently and allow adding new features without changing any existing code. Such design also allows reducing your Web API layer to a simple piece of infrastructure that doesn't require changing when new features are being added. You can read about this concept here (note: that article is about WCF, but the concept for Web API is the same) and here 是 Github显示如何在 WCF 和 Web 中实现此功能的存储库 API。

祝您在精通软件的过程中好运。

您可以通过两种方式简化此操作:

  1. 您的 PersonService 不依赖于 Role、Gender、Ethnicity 和 Prefix 服务,因为您不从其方法中调用它们。您的客户端代码调用的是 shell 而不是直接调用这些服务本身。如果是这样,那么您可以通过去掉这 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或Core的依赖,要看你的service是干什么的。如果你的服务只是调用核心,那么你自己去核心。如果您的服务正在执行某些验证或其他任何操作,您可能希望依赖它以避免在 PersonService 中复制相同的代码。