Asp.net mvc 4 支持工作流的MVC应用程序中的域驱动设计-设计决策

Asp.net mvc 4 支持工作流的MVC应用程序中的域驱动设计-设计决策,asp.net-mvc-4,domain-driven-design,repository-pattern,workflow-activity,service-locator,Asp.net Mvc 4,Domain Driven Design,Repository Pattern,Workflow Activity,Service Locator,我正在构建一个N层MVC4应用程序,它使用一个抽象的CommandProcessor层来验证和执行我的CommandModels,从而实现存储库和UnitOfWork模式以及域驱动设计 我现在开始学习工作流基础,并添加了一个处理用户注册的工作流项目。在工作流结束时,如果一切顺利,工作流将执行ApproveMembership CodeActivity: public sealed class ApproveMembership : CodeActivity { [RequiredArgu

我正在构建一个N层MVC4应用程序,它使用一个抽象的CommandProcessor层来验证和执行我的CommandModels,从而实现存储库和UnitOfWork模式以及域驱动设计

<>我现在开始学习工作流基础,并添加了一个处理用户注册的工作流项目。在工作流结束时,如果一切顺利,工作流将执行ApproveMembership CodeActivity:

public sealed class ApproveMembership : CodeActivity
{
    [RequiredArgument]
    public InArgument<string> UserEmail { get; set; }

    protected override void Execute(CodeActivityContext context)
    {
        IDatabaseFactory databaseFactory = new DatabaseFactory();
        IUnitOfWork unitOfWork = new UnitOfWork(databaseFactory);
        IUserRepository userRepository = new UserRepository(databaseFactory);

        string userEmail = UserEmail.Get(context);

        User user = userRepository.Get(u => u.Email == userEmail);

        if (user != null)
        {
            user.Activated = true;
            userRepository.Update(user);
            unitOfWork.Commit();
        }
    }
}
公共密封类批准成员资格:CodeActivity
{
[必需参数]
公共InArgument用户电子邮件{get;set;}
受保护的覆盖无效执行(CodeActivityContext上下文)
{
IDatabaseFactory databaseFactory=新的databaseFactory();
IUnitOfWork unitOfWork=新的unitOfWork(数据库工厂);
IUserRepository userRepository=新的userRepository(databaseFactory);
字符串userEmail=userEmail.Get(上下文);
User=userRepository.Get(u=>u.Email==userEmail);
如果(用户!=null)
{
user.Activated=true;
userRepository.Update(用户);
unitOfWork.Commit();
}
}
}
还有一个类似的RemoveMembership活动,如果用户从未验证,则会在一段时间后删除该用户

我的问题是,在我的工作流程中处理这个问题有意义吗?或者,在工作流中使用依赖项注入来获得CommandBus的更好方法是,该CommandBus将处理我必须创建的2个新的、几乎相同的命令模型,以及它们的验证和提交处理程序?在我的MVC AccountController中就是这样做的

    public class DeleteUserCommand : ICommand
    {
        public int UserId { get; set; }
    }
    public class ApproveUserCommand : ICommand
    {
        public int UserId { get; set; }
    }

    public sealed class RemoveMembership : CodeActivity
    {
        public InArgument<string> UserEmail { get; set; }

        private readonly ICommandBus commandBus;
        private readonly IUserRepository userRepository;

        public RemoveMembership(ICommandBus commandBus, IUserRepository userRepository)
        {
            this.commandBus = commandBus;
            this.userRepository = userRepository;
        }

        protected override void Execute(CodeActivityContext context)
        {
            string userEmail = UserEmail.Get(context);
            User user = userRepository.Get(u => u.Email == userEmail);

            if (user != null)
            {
                var command = new DeleteUserCommand
                {
                    UserId = user.UserId
                };

                IEnumerable<ValidationResult> errors = commandBus.Validate(command);
                if (!errors.Any())
                {
                    commandBus.Submit(command);
                }
            }
        }
    }
公共类DeleteUserCommand:ICommand
{
public int UserId{get;set;}
}
公共类ApproveUserCommand:ICommand
{
public int UserId{get;set;}
}
公开密封类RemoveMembership:CodeActivity
{
公共InArgument用户电子邮件{get;set;}
专用只读ICommandBus命令总线;
专用只读IUserRepository userRepository;
public RemoveMembership(ICommandBus commandBus、IUserRepository userRepository)
{
this.commandBus=commandBus;
this.userRepository=userRepository;
}
受保护的覆盖无效执行(CodeActivityContext上下文)
{
字符串userEmail=userEmail.Get(上下文);
User=userRepository.Get(u=>u.Email==userEmail);
如果(用户!=null)
{
var命令=新的DeleteUserCommand
{
UserId=user.UserId
};
IEnumerable errors=commandBus.Validate(命令);
如果(!errors.Any())
{
commandBus.Submit(命令);
}
}
}
}
显然,它的代码要多得多,但它的设计好吗

我觉得写这篇文章回答了我自己的问题,我想答案是肯定的。但我还是想听听专业人士的意见

我的问题是,在我的内心处理这件事有意义吗 工作流程

我会将CodeActivity中的代码封装到应用程序服务中,并使工作流引用该应用程序服务:

class UserApplicationService
{
    public void ApproveMembership(string userEmail) 
    { 
        var user = userRepository.Get(u => u.Email == userEmail);
        if (user != null)
        {
            user.Activated = true;
            userRepository.Update(user);
        }
    }
}


public sealed class ApproveMembership : CodeActivity
{
    [RequiredArgument]
    public InArgument<string> UserEmail { get; set; }

    protected override void Execute(CodeActivityContext context)
    {
        var userEmail = UserEmail.Get(context);
        this.userService.ApproveMembership(userEmail);
    }
}
类用户应用程序服务
{
public void ApproveMembership(字符串userEmail)
{ 
var user=userRepository.Get(u=>u.Email==userEmail);
如果(用户!=null)
{
user.Activated=true;
userRepository.Update(用户);
}
}
}
公共密封类批准成员:CodeActivity
{
[必需参数]
公共InArgument用户电子邮件{get;set;}
受保护的覆盖无效执行(CodeActivityContext上下文)
{
var userEmail=userEmail.Get(上下文);
this.userService.ApproveMembership(userEmail);
}
}
这样做的动机是WWF是体系结构中的一个基础设施组件,它可以很好地将基础设施与域逻辑解耦。WWF可以被类似NServiceBus的东西所取代,您可以在其中引用相同的应用程序服务。有人会说这是一个例子,但我认为分离域代码的基础结构在代码质量和对域进行推理的能力方面都是非常有益的

我还建议您尽可能多地将工作单元代码推送到基础架构中,这样应用程序服务就不必显式地调用
Commit

还是在工作流中使用依赖项注入的更好方法 要获得一个CommandBus来处理2个新的、几乎 我必须创建相同的命令模型,以及 它们的验证和提交处理程序


这似乎更符合我的建议,但是基于您的代码示例,我建议进一步将CodeActivity中的大部分逻辑提取到应用程序服务中,或者以这样一种方式构造应用程序,即您可以在不需要访问存储库的情况下发送命令。

谢谢您的精彩回答。至于服务依赖性,我发现ServiceLocator模式与WWF中的DI等效,并将使用此模式来完成您所说的。再次感谢。