服务层依赖注入

问题描述:

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

这是web api会调用的。

enter image description here

这里的问题,要求IPersonService时,人就会有性别定义,这将有一个名称,角色和种族。我正在使用构造函数注入,并且不确定是否应该调用GenderService,还是应该调用业务层(在这种情况下,由Core定义)。

enter image description here

我应该打电话喜欢的图片服务高于或低于

enter image description here

这是我一个人服务的样子

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是我的问题,它的声音就像寻找某人某事的依赖性。

您可以通过两种方式简化了这一点:

  1. 您PersonService看起来并不取决于本身的角色,性别,种族和前缀服务,您不要从它的方法调用它们。它是客户端代码调用的一个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中,那么你会注入依赖关系的方法而不是构造函数。

    关于服务或核心的依赖关系,它取决于您的服务的功能。如果你的服务只是调用核心,那么你自己去核心。如果您的服务正在进行一些验证或其他任何事情,您可能需要依赖它来避免复制PersonService中的相同代码。

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中实现这一点。

祝您在寻求软件精通方面一切顺利。

+0

谢谢,所以从用户角度来看,Personservice应该返回基本的id,密码,电子邮件但是角色,性别只应该给genderService,两个服务不应该互相对话? – Jseb

+0

@Jseb:这不是我所宣传的。我正在推广的是一个模型,其中每个查询(例如'GetAllPerson'和'GetPersonByEmail')都包含在它自己的类中。这样的类可以依赖于它所需要的东西,但在大多数情况下只会使用'DbContext'来查询数据库。 – Steven