gpt4 book ai didi

c# - 如何在 DDD 和存储库模式中对此建模

转载 作者:行者123 更新时间:2023-11-30 18:01:11 26 4
gpt4 key购买 nike

我想像这样模拟服务

public class FooService
{
public GetById(ISecurityContext context, id)
{
//checking context has right to view
//calling Foo repository to getById
}

public Add(ISecurityContext context,Foo fooEntity)
{
//checking context has right to add
//calling Foo repository to add
}



}

在上面的方法中我想传递不同类型的 SecurityContext所以我所做的是

Public Interface ISecurityContext
{

}

UsernamePasswordContext : ISecurityContext
{
public string Username { get; set; }
public string Password { get;set; }

}

SessionContext : ISecurityContext
{
public string SessionId {get ; set;}
}

所以在我的账户服务中我有一个方法

public class AccountService
{
public Account GetAccountFromSecurityContext(ISecurityContext context)
{
if(context is UsernamePasswordContext)
return GetAccountByUsernamePassword(context.Username,context.Password);
else if (context is SessionContext)
return GetAccountBySessionId(context.SessionId);

// more else if for different type of context
}


}

在上面的代码中我不喜欢那么多 if else所以我尝试引入多态性

所以在我的 ISecurityContext 接口(interface)中我添加了一个所有子类都将实现的 GetAccount 方法

Public Interface ISecurityContext
{
Account GetAccount();
}


UsernamePasswordContext : ISecurityContext
{
public string Username { get; set; }
public string Password { get;set; }

public Account GetAccount()
{
//call account service
GetAccountByUsernamePassword(this.Username,this.Password);
}


}

我的账户服务会变成这样

public class AccountService
{
public Account GetAccountFromSecurityContext(ISecurityContext context)
{
context.GetAccount();
}

}

但这里的问题是我正在从我的 UsernamePasswordContext POCO 调用服务/存储库,这会破坏 DDD

那么我可以通过哪些其他方式对这种情况进行建模。

最佳答案

我认为您离解决方案不远了。在这种情况下,我会在您的 AccountService 中注入(inject)一个工厂,它将承担 if..then..else 的责任。然后,工厂可以使用许多可能的解决方案之一。

我马上要做的一个更改是让您的 AccountService 实现一个接口(interface),以便以后更容易注入(inject)。假设您正在使用某个 IOC 容器,您不必太担心依赖性,因为您让容器处理所有这些。

这是您已有的部分,并进行了一些小的调整:

public class Account
{
//some account information and behavior
}

public interface ISecurityContext
{
}

public class UsernamePasswordContext : ISecurityContext
{
public string Username { get; set; }
public string Password { get; set; }
}

public class SessionContext : ISecurityContext
{
public string SessionId { get; set; }
}

这是您的帐户服务及其实现:

public interface IAccountService
{
Account GetAccountFromSecurityContext(ISecurityContext securityContext);
}

public class AccountService : IAccountService
{
readonly IAccountFactory _accountFactory;

public AccountService(IAccountFactory accountFactory)
{
_accountFactory = accountFactory;
}

public Account GetAccountFromSecurityContext(ISecurityContext securityContext)
{
Account account = _accountFactory.Create(securityContext);
return account;
}
}

因此,您可以在这里看到我注入(inject)了一个 IAccountFactory,它将处理 Account 对象的实际创建(检索,无论什么)。此时我们只关心帐户是否被创建/检索...我们不关心如何创建/检索。


有几种方法可以实现这样的工厂。一种方法是使用一种策略模式,其中您有一个知道如何解析帐户的小部件列表。然后你只需选择匹配的小部件(策略)并执行它。与此类似的是使用 IOC 或服务定位器解析先前已在应用程序配置中注册的类型的工厂。

以示例的方式,这是使用 CommonServiceLocatorIAccountFactory 的一种可能实现:

public interface IAccountFactory
{
Account Create(ISecurityContext securityContext);
}

public class ServiceLocatorAccountFactory : IAccountFactory
{
readonly IServiceLocator _serviceLocator;

public ServiceLocatorAccountFactory(IServiceLocator serviceLocator)
{
_serviceLocator = serviceLocator;
}

public Account Create(ISecurityContext securityContext)
{
var resolverType = typeof (IAccountResolver<>).MakeGenericType(securityContext.GetType());
dynamic resolver = _serviceLocator.GetInstance(resolverType);
return resolver.Resolve(securityContext);
}
}

我这里的工厂进入服务定位器上下文并获取与我们的安全上下文匹配的任何解析器。以下是可能的解析器的几个示例:

public interface IAccountResolver<in TSecurityContext> where TSecurityContext : ISecurityContext
{
Account Resolve(TSecurityContext securityContext);
}

public class UsernamePasswordAccountResolver : IAccountResolver<UsernamePasswordContext>
{
readonly IRepository _repository;

public UsernamePasswordAccountResolver(IRepository repository)
{
_repository = repository;
}

public Account Resolve(UsernamePasswordContext securityContext)
{
var account = _repository.GetByUsernameAndPassword(securityContext.Username,
securityContext.Password);

return account;
}
}

public class SessionAccountResolver : IAccountResolver<SessionContext>
{
public Account Resolve(SessionContext securityContext)
{
//get the account using the session information
return someAccount;
}
}

唯一剩下的就是在您的 IOC 容器中注册解析器,以便在服务定位器尝试在工厂中解析它们时可以找到它们。

关于c# - 如何在 DDD 和存储库模式中对此建模,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9312462/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com