简体   繁体   English

使用Anemic域模型的服务之间的循环引用

[英]Circular reference between the services using the Anemic domain model

I am working on a project with a complex business. 我正在从事一项业务复杂的项目。 Consider two classes : AccountService and SchoolService 考虑两个类:AccountService和SchoolService

I am using Unity and the dependency resolver of the Web API to implement dependency injection in the constructor. 我正在使用Unity和Web API的依赖项解析器在构造函数中实现依赖项注入。

The school service uses the account service in some methods, also the account service uses the school service. 学校服务以某种方式使用帐户服务,帐户服务也使用学校服务。 All this is required in the business of the project. 所有这些都是项目业务所必需的。 This will cause circular dependency, and it is not possible to move the methods from one class into another. 这将导致循环依赖,并且无法将方法从一个类移到另一个类。

Can you please provide any idea on how to solve this ? 您能提供任何解决方法的想法吗?

Here is an example: 这是一个例子:

public class SchoolBLC : ISchoolBLC
{
    public School GetSchool(int schoolId)
    {
        ...
    }

    public bool RenewRegistration(int accountId)
    {
        bool result = true;

        IAccountBLC accountBLC = new AccountBLC();
        // check some properties related to the account to decide if the account can be renewed
        // ex : the account should not be 5 years old
        // check the account created date and do renewal

        return result;
    }
}

public class AccountBLC : IAccountBLC
{
    public void ResetAccount(int accountId)
    {
        ISchoolBLC schoolBLC = new SchoolBLC();
        School accountSchool = schoolBLC

        // get the school related to the account to send a notification 
        // and tell the school that the user has reset his account
        // reset account and call the school notification service
    }

    public Account GetAccount(int accountId)
    {
        ...
    }
}

The two classes are referencing each other, this is the situation for 70% of the BLCs in the project. 这两个类相互引用,这是项目中70%的BLC的情况。

If you absolutely have to do it that way you can have an interface that does your IoC logic and resolve that to an implementation that wraps Unity's resolution, eg 如果绝对必须这样做,则可以有一个接口执行IoC逻辑并将其解析为包装Unity分辨率的实现,例如

public interface ITypeResolver
{
    T Resolve<T>();
}

Then you can pass that interface to both services in the constructor and use it to lazy-resolve the other service before you use it, outside the constructor. 然后,您可以将该接口传递给构造函数中的两个服务,并在构造函数之外使用它来延迟解析另一个服务,然后再使用它。

That way when both services are initialized they will not have a direct dependency on the other service, only on ITypeResolver 这样,当两个服务都初始化时,它们将不会直接依赖于另一个服务,而仅依赖于ITypeResolver

I will do as suggested by @KMoussa but with some modifications: 我将按照@KMoussa的建议进行操作,但需要进行一些修改:

The project is using the anemic model, so i will use a context pattern to lazy load and create any service, and the context will be passed as parameter to the service constructor. 该项目正在使用贫血模型,因此我将使用上下文模式来延迟加载并创建任何服务,并且上下文将作为参数传递给服务构造函数。

public class SDPContext : ISDPContext
{
    private ITypeResolver _typeResolver;

    public Account CurrentUser { get; set; }

    public IAccountService AccountService
    {
        get
        {
            // lazy load the account service
        }
    }

    public ISchoolService SchoolService
    {
        get
        {
            // lazy load the schoolservice
        }
    }

    public SDPContext(ITypeResolver typeResolver)
    {
        this._typeResolver = typeResolver;
    }
}

public class ServiceBase
{
    public ISDPContext CurrentContext { get; set; }

    public ServiceBase(ISDPContext context)
    {
        this.CurrentContext = context;
    }
}

public class AccountService : ServiceBase, IAccountService
{
    public AccountService(ISDPContext context) : base(context)
    {

    }

    public bool ResetAccount(int accountId)
    {
        // use base.Context.SchoolService to access the school business
    }
}

public class SchoolService : ServiceBase, ISchoolService
{
    public SchoolService(ISDPContext context) : base(context)
    {
        //this._accountService = accountService;
    }

    public void RenewRegistration(int accountId)
    {
        // use the base.Context.Account service to access the account service
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM