我是Onion Architecture的新手,正在尝试将其应用到ASP.NET项目中。我目前正在实现ASP.NET Identity,并希望使用其UserManager
类来存储用户。
根据我对Onion Architecture的了解,我应该在域层中创建一个可用于包装UserManager
的接口。
public interface IUserManager
{
public Task CreateAsync(string username, string password);
}
然后在基础结构层中,我将实现自己的UserManager
,它包装ASP.NET标识UserManager
。
using Microsoft.AspNetCore.Identity;
public class MyUserManager : IUserManager
{
private readonly UserManager<IdentityUser> _userManager;
public UserManager(UserManager<IdentityUser> userManager)
{
_userManager = userManager;
}
public async Task CreateAsync(string username, string password)
{
var user = new IdentityUser { UserName = username };
await _userManager.CreateAsync(user, password);
}
}
问题
我的问题是,我也想从UserManager.CreateAsync(...)
返回可能的错误,而不是返回void
的返回类型。看起来像这样:
public class IdentityResult
{
public bool Succeeded { get; set; }
public IEnumerable<string> Errors { get; set; } // Some Error type instead of a string would be better
}
我必须在域层中定义此DTO,因为它们必须是IUserManager
接口的一部分,但是我不确定这是否是正确的方法。从我发现的开源项目中,我看不到它们在域层中使用DTO,而且人们似乎在说DTO通常是应用程序方面的问题,但我可能会对此深思熟虑。也许我已经对目前的方式采取了错误的方法?
答案 0 :(得分:1)
从软件体系结构的角度来看,接口不仅是实际的interface
定义(即您的IUserManager
),而且还是两个组件之间契约的一部分,例如功能,输入和输出DTO,以及实现可能引发的异常和调用者必须能够捕获的异常。
在.NET中,您需要在同一项目中定义所有这些内容,以便在必要时可以将其作为软件包分发。在洋葱架构中,从技术上讲,它们是核心的一部分,但这并不意味着整个核心需要在单个项目中定义。如果您将核心实现与合同分开,则可以分发合同,而无需同时分发实施。