使用贫血域模型的服务之间的循环引用
Circular reference between the services using the Anemic domain model
我正在从事一个业务复杂的项目。
考虑两个 classes:AccountService 和 SchoolService
我正在使用 Unity 和 Web 的依赖解析器 API 在构造函数中实现依赖注入。
学校服务在某些方面使用了帐号服务,帐号服务也使用了学校服务。所有这些都是项目业务所需要的。这将导致循环依赖,并且无法将方法从一个 class 移动到另一个
能否请您提供有关如何解决此问题的任何想法?
这是一个例子:
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)
{
...
}
}
两个class相互引用,项目中70%的BLC都是这种情况。
如果你绝对必须那样做,你可以有一个接口来执行你的 IoC 逻辑并将其解析为包装 Unity 分辨率的实现,例如
public interface ITypeResolver
{
T Resolve<T>();
}
然后您可以将该接口传递给构造函数中的两个服务,并在使用它之前在构造函数外部使用它来延迟解析另一个服务。
这样,当两个服务都被初始化时,它们将不会直接依赖于另一个服务,只依赖于 ITypeResolver
我会按照@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
}
}
我正在从事一个业务复杂的项目。 考虑两个 classes:AccountService 和 SchoolService
我正在使用 Unity 和 Web 的依赖解析器 API 在构造函数中实现依赖注入。
学校服务在某些方面使用了帐号服务,帐号服务也使用了学校服务。所有这些都是项目业务所需要的。这将导致循环依赖,并且无法将方法从一个 class 移动到另一个
能否请您提供有关如何解决此问题的任何想法?
这是一个例子:
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)
{
...
}
}
两个class相互引用,项目中70%的BLC都是这种情况。
如果你绝对必须那样做,你可以有一个接口来执行你的 IoC 逻辑并将其解析为包装 Unity 分辨率的实现,例如
public interface ITypeResolver
{
T Resolve<T>();
}
然后您可以将该接口传递给构造函数中的两个服务,并在使用它之前在构造函数外部使用它来延迟解析另一个服务。
这样,当两个服务都被初始化时,它们将不会直接依赖于另一个服务,只依赖于 ITypeResolver
我会按照@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
}
}