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

时间:2016-10-17 19:21:58

标签: c# dependency-injection circular-dependency anemic-domain-model

我正在从事一项复杂业务的项目。 考虑两个类:AccountService和SchoolService

我使用Unity和Web API的依赖项解析器在构造函数中实现依赖注入。

学校服务在某些方法中使用帐户服务,帐户服务也使用学校服务。所有这些都是项目业务所必需的。这将导致循环依赖,并且无法将方法从一个类移动到另一个类。

您能否就如何解决这个问题提出任何意见?

以下是一个例子:

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)
    {
        ...
    }
}

这两个类是相互引用的,这是项目中70%的BLC的情况。

2 个答案:

答案 0 :(得分:0)

如果您必须这样做,您可以拥有一个执行IoC逻辑的接口,并将其解析为包含Unity解析的实现,例如

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

然后,您可以将该接口传递给构造函数中的两个服务,并在构造函数之外使用它来延迟解析其他服务。

这样,当两个服务都被初始化时,它们不会直接依赖于其他服务,只能在ITypeResolver

答案 1 :(得分:0)

我会按照@KMoussa的建议做,但做了一些修改:

该项目正在使用贫血模型,因此我将使用上下文模式来延迟加载并创建任何服务,并将上下文作为参数传递给服务构造函数。

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
    }
}