使用构造函数来设置属性

时间:2018-10-23 05:55:43

标签: c# swagger asp.net-core-webapi swashbuckle

我正在构建一个API,并使用swagger测试端点。我有一个ProductDTO:

public string ProductName { get; set; }
.
.
.
public Price Price { get; set; }

在此DTO中,我想使用在整个代码中都使用的Price类。价格类别如下:

public class Price
{
    public Price(decimal amount, string currency)
    {
        Amount = amount;
        Currency = currency;
    }

    public decimal Amount { get; private set; }
    public string Currency { get; private set; }
}

但是由于在Price类中使用了私有的setter,所以我不能使用swagger设置这些值(它在属性上具有readonly)。我真的很喜欢这样的方法:拥有私有的setter和使用构造函数设置值,这是公共的。我有什么办法可以使用招摇设置Price类的值,而仍然在属性上使用私有设置器?

2 个答案:

答案 0 :(得分:3)

更新:我的原始答案(请参见下文)是不可能的,但是,这实际上取决于项目中使用的序列化库。

例如,Newtonsoft的Json.NET允许您通过构造函数设置类的某些属性(注意:如果您的类带有多个构造函数,请应用JsonConstructorAttribute):

public class Price
{
    [JsonConstructor]
    public Price(decimal amount, string currency)
    {
        Amount = amount;
        Currency = currency;
    }

    public decimal Amount { get; private set; }
    public string Currency { get; private set; }
}

原始答案

否,这是不可能的。因为如果您将属性设为私有,然后仅通过构造函数对其进行初始化,则反序列化器将不知道这些属性应如何映射到您的后端(DTO)模型。

因此,在使用DTO时,通常不会看到人们通过构造函数进行初始化。

此外,由于在整个代码中都使用Price类,因此您将“域模型”与“视图模型”(=用于与客户端通信的模型)混合在一起–这是一种务实的方法,但并非如此以DDD等风格进行宣传。在这种情况下,如果要在属性上使用不同的属性或访问修饰符,则应创建一个专用的PriceDTO,该DTO映射到Price实体,但具有公共设置方法和获取方法。

另一种选择是将用于将数据发送到客户端(通过GET)的端点所使用的模型与将数据作为有效负载接收以创建或更新事物的端点所使用的模型(通过POST / PATCH /放)。但是,这通常以冗余为代价,因为两种情况下的模型通常非常相似。

答案 1 :(得分:0)

添加此架构过滤器对我有用。

public class AddReadOnlyPropertiesFilter : ISchemaFilter
{
    public void Apply(OpenApiSchema schema, SchemaFilterContext context)
    {
        if (schema?.Properties?.Count > 0)
            schema.Properties.Values.SingleOrDefault(v => v.ReadOnly = false);
    }
}