c# - 如何构建F#类型的业务规则?

标签 c# f# domain-driven-design option-type

我正在尝试在 F# 中构建一个类型,当我获得该类型的对象时,我可以确定它处于有效状态。
该类型称为 JobId,它只包含一个 Guid
业务规则是:它必须是一个 Guid - 但不能为空 Guid。
我已经在 C# 中实现了该类型,但现在我想将它移植到 F# 类库中。

那是 C# 类型:

public sealed class JobId
{
    public string Value { get; }

    private JobId(string value)
        => Value = value;

    public static JobId Create()
        => new JobId(Guid.NewGuid().ToString("N"));

    public static Option<JobId> Create(Guid id)
        => id == Guid.Empty
        ? None
        : Some(new JobId(id.ToString("N"));

    public static Option<JobId> Create(string id)
    {
        try
        {
            var guid = new Guid(id);
            return Create(guid);
        }
        catch (FormatException)
        {
            return None;
        }
    }
}

那么我该如何在 F# 中构建它呢?谢谢!

更新 1:
我试图将它实现为像这样的可区分联合类型:

type JobId =
    | JobId of string

但问题是,我无法使用该方法定义任何业务规则。
所以最后的问题是:如何确保JobId中的string存在于一个 某种格式?

最佳答案

我修改了 Tomas 的答案,使用 DU 而不是类来保持适当的相等性和比较,例如,允许 JobId 按预期作为分组键工作。

[<AutoOpen>]
module JobId =
    open System
    type JobId = private JobId of string with
        static member Create() = JobId(Guid.NewGuid().ToString("N"))

        static member Create(id:Guid) =
            if id = Guid.Empty then None
            else Some(JobId(id.ToString("N")))

        static member Create(id:string) =
            try JobId.Create(Guid(id))
            with :? FormatException -> None

您必须将类型放在模块内,然后您无法直接在该模块外访问 DU 构造函数:

JobId.Create (System.Guid.NewGuid()) // Some (JobId "1715d4ae776d441da357f0efb330be43")
JobId.Create System.Guid.Empty // None
JobId System.Guid.Empty // Compile error

关于c# - 如何构建F#类型的业务规则?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58974451/

相关文章:

c# - Entity Framework - 使用 Web.Config 连接字符串

f# - System.MissingMethodException : Method not found: 'FSharp. Data.HttpResponse

database - F# 如何展平与其他类型混合的嵌套结果类型

c# - 分离领域模型和数据模型

c# - 哪个 .nuget 包包含 String.Compare 和 StringComparison 参数?

c# - 这种 bool 方法是一种不好的做法吗?

C# Razor 静态助手错误 “Collection Was Modified”

f# - 为什么当我尝试从此模块返回可变列表的内容时,总是得到一个空列表?

f# - F#中的条件求和

domain-driven-design - 领域驱动设计如何处理报告?