【问题标题】:Is it OK to have optional parameters in DTOs?在 DTO 中有可选参数可以吗?
【发布时间】:2013-09-06 11:23:53
【问题描述】:

我在这里有点困惑。我有一个场景,根据选择的选项,只有我的 DTO 的某些属性有效。所以,我想出了下面的设计。

[DataContract]
class MyDTO
{
    [DataMember]
    public BaseData CommonData { get; set; }
    [DataMember]
    public Options AvailableOptions { get; set; }
    [DataMember]
    public Option1Data Data1 { get; set; }
    [DataMember]
    public Option2Data Data2 { get; set; }
}
[DataContract]
public class BaseData
{
    [DataMember]
    public int BaseVar1 { get; set; }        
}

[DataContract]
public enum Options
{
    [EnumMember]
    Option1,
    [EnumMember]
    Option2
}

[DataContract]
public class Option1Data
{
    [DataMember]
    public string Option1Var1 { get; set; }
}

[DataContract]
public class Option2Data
{
    [DataMember]
    public string Option2Var1 { get; set; }
}

但显然MyDTO 类违反了OCP 原则。每当在 Options 枚举中添加一个新选项时,我需要更改 MyDTO 以添加一个属性来检索该选项的数据。

在这种情况下可以更改MyDTO 还是您有更好的设计?

【问题讨论】:

    标签: c# design-patterns dto


    【解决方案1】:

    继承呢?

    [DataContract]
    [KnownType(typeof(Option1))]
    [KnownType(typeof(Option2))]
    public abstract class BaseData
    {
        [DataMember]
        public int BaseVar1 { get; set; }        
    }
    
    [DataContract]
    public class Option1 : BaseData
    {
        [DataMember]
        public string Option1Var1 { get; set; }
    }
    
    [DataContract]
    public class Option2 : BaseData
    {
        [DataMember]
        public string Option2Var1 { get; set; }
    }
    

    您还可以添加enum 以方便使用switch 等,但它不需要是[DataMember],因为它实际上是多余的信息:

    public enum Options
    {
        Option1,
        Option2
    }
    
    [DataContract]
    [KnownType(typeof(Option1))]
    [KnownType(typeof(Option2))]
    public abstract class BaseData
    {
        [DataMember]
        public int BaseVar1 { get; set; }        
        [IgnoreDataMember]
        public abstract Options Option {get;}
    }
    
    [DataContract]
    public class Option1 : BaseData
    {
        [DataMember]
        public string Option1Var1 { get; set; }
        [IgnoreDataMember]
        public override Options Option {get { return Options.Option1; } }
    }
    
    [DataContract]
    public class Option2 : BaseData
    {
        [DataMember]
        public string Option2Var1 { get; set; }
        [IgnoreDataMember]
        public override Options Option {get { return Options.Option2; } }
    }
    

    【讨论】:

    • 正如我所说,我有点困惑。一般来说,建议优先考虑组合而不是继承,以避免与基类的紧密耦合(我猜,如果您在 BaseData 中添加一个新属性,它将自动在其所有派生类型中被继承,而某些派生类型可能不需要) .所以,我在 MyDTO 类中使用了 BaseData 的组合。
    • @Imran 然后坦率地说,使用您现有的代码 - 但您也可以删除枚举 - 它没有添加任何内容并且是多余的。调用者只需检查哪些数据可用(通过检查null 等)。
    • 我对现有代码不满意 :)。我同意枚举是多余的。为了方便起见,我添加了它,以便根据选项准确地找到属性。但是,我想我现有的代码有一个优点(真的吗?),我不需要根据抽象 Option 方法将 BaseData 向下转换为 Option1 或 Option2。
    • @Imran meh;实际上,演员表和成员访问之间没有太大区别
    • DTO 是否需要符合 OCP 标准?可变性肯定是其功能所固有的吗?
    猜你喜欢
    • 1970-01-01
    • 2011-09-25
    • 2016-03-25
    • 2012-12-11
    • 2011-04-15
    • 2023-04-04
    • 1970-01-01
    • 2013-07-04
    • 1970-01-01
    相关资源
    最近更新 更多