Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/271.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# csharp与面向铁路的程序设计_C#_Functional Programming - Fatal编程技术网

C# csharp与面向铁路的程序设计

C# csharp与面向铁路的程序设计,c#,functional-programming,C#,Functional Programming,从这个惊人的课程: 我正在尝试应用领域驱动设计、功能原理和面向铁路的编程方法 有人能帮我把下面的代码精简一下吗 我知道我需要创建一些T扩展方法的结果,我尝试过,但无法让它们工作 伪代码所做的是 创建电子邮件值对象->电子邮件。创建 创建和EmailAddress实体->EmailAddress.Create 结果存储在T变量emailAddress的结果中 (我们在点击数据库进行更新操作之前执行此操作,如果获得无效的电子邮件地址,则根本没有意义点击数据库) (由于以后需要使用可变的emailAd

从这个惊人的课程:

我正在尝试应用领域驱动设计、功能原理和面向铁路的编程方法

有人能帮我把下面的代码精简一下吗

我知道我需要创建一些T扩展方法的结果,我尝试过,但无法让它们工作

伪代码所做的是

  • 创建电子邮件值对象->电子邮件。创建
  • 创建和EmailAddress实体->EmailAddress.Create
  • 结果存储在T变量emailAddress的结果中
  • (我们在点击数据库进行更新操作之前执行此操作,如果获得无效的电子邮件地址,则根本没有意义点击数据库)

    (由于以后需要使用可变的emailAddress,铁路中断了:(很遗憾!!甚至最糟糕的是…没有检查失败的emailAddress结果实体,应该检查)

  • 通过播放器存储库->repository.GetAsync(“336978e9-837a-4e8d-6b82-08d6347fe6b6”)按Id获取播放器
  • 结果存储在T变量playerResult的结果中
  • (由于以后需要使用变量playerResult,铁路再次中断:(太遗憾了!!甚至最糟糕的是…没有检查返回结果失败的玩家实体,应该检查)

  • 将新创建的电子邮件地址添加到播放器电子邮件地址集合->p.AddEmailAddress(EmailAddress.Value)
  • (铁路又被破坏了:(太可悲了!!。甚至最糟糕的是…未能将电子邮件地址添加到玩家集合中未被检查,它应该被检查)

  • 最后,异步保存更改并返回受影响的行数
  • 下面的代码行为简洁而减少

       var emailAddress = Email.Create("jamesbond@gmail.com")
                    .OnSuccess(email => EmailAddress.Create(email, default));
    
                var playerResult = await emailAddress.OnSuccess(e => repository.GetAsync("336978e9-837a-4e8d-6b82-08d6347fe6b6")).ToResult(""));
    
                var wasAdded = playerResult.OnSuccess(p => p.AddEmailAddress(emailAddress.Value));
    
                var wasSaved = await wasAdded.OnSuccess(a => unitOfWork.SaveChangesAsync());
    
                var message = wasSaved
                    .Ensure(r => r > 0, "No record were saved")
                    .OnBoth(result => result.IsSuccess ? "Ok" : result.Error);
    
    下面是方法的签名

    Email.Create -> public static Result<Email> Create(string email)
    EmailAddress.Create -> public static Result<EmailAddress> Create(Email mailAddress, string mailAddressInstructions)
    GetAsync -> public Task<Maybe<Player>> GetAsync(string id)
    AddEmailAddress -> public Result<bool> AddEmailAddress(EmailAddress emailAddress)
    SaveChangesAsync -> public async Task<int> SaveChangesAsync()
    
    Email.Create->公共静态结果创建(字符串电子邮件)
    EmailAddress.Create->公共静态结果创建(emailmaildress,stringmaildAddressInstructions)
    GetAsync->公共任务GetAsync(字符串id)
    AddEmailAddress->公共结果AddEmailAddress(EmailAddress EmailAddress)
    SaveChangesAsync->公共异步任务SaveChangesAsync()
    
    我执行了一些单元测试,代码正在运行,但就您所见,它还远未面向铁路


    提前感谢。

    就我个人而言,我更喜欢使用局部变量;我认为它更易于维护。在处理工作单元等非功能性设计时尤其如此。但是,您想要做的是使用功能性编程结构

    要删除局部变量,需要使用两种方法。首先,monad需要一个
    bind
    ;这使您可以展开多个值,然后将它们映射到一个新值。第二种方法是元组

    我发现让我的域类型本身对函数类型一无所知是很有用的。所以只有常规方法之类的,不返回
    结果
    类型:

    private static Task<Player> RepositoryGetAsync(string id) => Task.FromResult(new Player());
    private static Task<int> RepositorySaveChangesAsync() => Task.FromResult(0);
    
    public sealed class Player
    {
        public bool AddEmailAddress(EmailAddress address) => true;
    }
    
    public sealed class Email
    {
        public Email(string address) => Address = address ?? throw new ArgumentNullException(nameof(address));
    
        public string Address { get; }
    }
    
    public sealed class EmailAddress
    {
        public static EmailAddress Create(Email address, int value) => new EmailAddress();
    }
    
    如果我们开始使用元组,那么我们可以组合几个变量。语法有点笨拙(例如,解构lambda参数),但这是可行的:

    static async Task Main(string[] args)
    {
        var emailAddressAndPlayerResult = await Try.Create(() => new Email("jamesbond@gmail.com"))
                .Map(email => EmailAddress.Create(email, default))
                .Map(async emailAddress => (emailAddress, await RepositoryGetAsync("336978e9-837a-4e8d-6b82-08d6347fe6b6")));
    
        var wasAdded = emailAddressAndPlayerResult.Map(((EmailAddress Address, Player Player) v) => v.Player.AddEmailAddress(v.Address));
    
        var wasSaved = await wasAdded.Map(_ => RepositorySaveChangesAsync());
    
        if (wasSaved.Value == 0)
            throw new Exception("No records were saved");
    }
    
    一旦我们在混合中有了元组,其余的变量就可以很好地折叠起来。剩下的唯一尴尬的部分是
    await
    通常需要括号。例如,此代码与上面的代码相同:

    static async Task Main(string[] args)
    {
        var wasAdded =
            (
                await Try.Create(() => new Email("jamesbond@gmail.com"))
                    .Map(email => EmailAddress.Create(email, default))
                    .Map(async emailAddress => (emailAddress, await RepositoryGetAsync("336978e9-837a-4e8d-6b82-08d6347fe6b6")))
            )
            .Map(((EmailAddress Address, Player Player) v) => v.Player.AddEmailAddress(v.Address));
    
        var wasSaved = await wasAdded.Map(_ => RepositorySaveChangesAsync());
    
        if (wasSaved.Value == 0)
            throw new Exception("No records were saved");
    }
    
    现在,当我们组合这些变量时,您可以看到
    await
    表达式是如何在道路上产生“颠簸”的。丑陋但可行。要删除最后一个变量:

    static async Task Main(string[] args)
    {
        var wasSaved =
            await
            (
                await Try.Create(() => new Email("jamesbond@gmail.com"))
                    .Map(email => EmailAddress.Create(email, default))
                    .Map(async emailAddress => (emailAddress, await RepositoryGetAsync("336978e9-837a-4e8d-6b82-08d6347fe6b6")))
            )
            .Map(((EmailAddress Address, Player Player) v) => v.Player.AddEmailAddress(v.Address))
            .Map(_ => RepositorySaveChangesAsync());
    
        if (wasSaved.Value == 0)
            throw new Exception("No records were saved");
    }
    

    重申一下我在一开始所说的,这是可能的,但在我看来,这很难看,而且不易维护。底线是C#是一种命令式语言,而不是函数式语言。在部分代码中采用函数式语言的某些方面可以使它更优雅;试图强制所有代码都具有完全的功能性是不可能的无法维护的秘诀。

    感谢您的回复。我会尝试更好地理解您的建议和发布的代码。链接到结果和可能的定义:
    static async Task Main(string[] args)
    {
        var wasSaved =
            await
            (
                await Try.Create(() => new Email("jamesbond@gmail.com"))
                    .Map(email => EmailAddress.Create(email, default))
                    .Map(async emailAddress => (emailAddress, await RepositoryGetAsync("336978e9-837a-4e8d-6b82-08d6347fe6b6")))
            )
            .Map(((EmailAddress Address, Player Player) v) => v.Player.AddEmailAddress(v.Address))
            .Map(_ => RepositorySaveChangesAsync());
    
        if (wasSaved.Value == 0)
            throw new Exception("No records were saved");
    }