C#属性完全相同,在两个地方定义

时间:2010-04-23 16:58:39

标签: c# .net inheritance properties

我有以下课程:

  1. Defect - 表示可在数据库中找到的一种数据
  2. FilterQuery - 提供了一种通过设置简单布尔过滤器来查询数据库的方法
  3. DefectFilterQuery都实现了相同的界面:IDefectProperties。此接口指定数据库中的特定字段。不同的类具有返回Defect个实例列表的方法。使用FilterQuery,您可以为IDefectProperties的一部分实现的特定属性指定一些过滤器,然后运行查询并返回Defect个实例的列表。

    我的问题是,我最终在FilterQueryDefect中实现了完全相同的一些属性。这两个本质上是不同的类,它们只是共享一些相同的属性。例如:

    public DateTime SubmitDateAsDate
    {
        get { return DateTime.Parse(SubmitDate); }
        set { SubmitDate = value.ToString(); }
    }
    

    这是IDefectProperties所需的属性,取决于其他属性SubmitDate,该属性返回string而不是DateTime。现在SubmitDateDefectFilterQuery中的实现方式不同,但SubmitDateAsDate完全相同。有没有办法可以仅在SubmitDateAsDateDefectFilterQueryFilterQuery作为属性进行定义? Defect和{{1}}已经从两个不同的类继承,我认为无论如何共享一个祖先是没有意义的。我也愿意接受有关我的设计的建议。

6 个答案:

答案 0 :(得分:5)

当继承没有意义时,组合通常会这样做。

internal class DefectPropertyInternal
{
  private IDefectproperty dp
  public DefectPropertyInternal(IDefectproperty dp)
  {
     this.dp = dp;
  }

  public DateTime SubmitDateAsDate
  {
    get { return DateTime.Parse(dp.SubmitDate); }
    set { dp.SubmitDate = value.ToString(); }
  }

}

public class Defect : IDefectProperty
{
  private DefectPropertyInternal dpi;

  public Defect()
  {
     this.dpi = new DefectpropertyInternals(this);
  }

 public DateTime SubmitDateAsDate
 {
    get { return dpi.SubmitDateAsDate; }
    set { dpi.SubmitDateAsDate = value; }
 }

}

通过这种方式,DefectPropertyInternals实现了FilterQuery和Defect的所有共享功能,而不必在每个类中重复这一功能。

答案 1 :(得分:2)

不,没有办法像你描述的那样完全做到这一点。

但是。您遇到此问题的事实意味着您的初始设计可能不是最佳设计。我不知道你的整个问题,所以请不要太认真地对待我的建议,但是立刻想到的是摆脱FilterQuery中的接口实现,而是让它接受(或暴露)一个实例Defect的{​​{1}},并使用该缺陷的属性进行过滤。可能有用的另一件事是拥有一个“存储”结构,它将拥有所有数据字段,并且Defect和FilterQuery都会包含它。

答案 2 :(得分:2)

如果继承不合适并且您想重用代码,则必须使用任一组合(对于您所描述的简单案例可能过度杀戮)或extension methods

扩展方法是在C#中模拟多重继承的好方法,尽管没有扩展属性("maybe someday" says Eric Lippert)。如果你愿意放弃属性语义,你可以这样做:

public static DateTime GetSubmitDateAsDate(this IDefectProperties defectProperties) {
    return DateTime.Parse(defectProperties.SubmitDate);
}

public static void SetSubmitDateAsDate(this IDefectProperties defectProperties, DateTime dateTime) {
    defectProperties.SubmitDate = dateTime.ToString();
}

答案 3 :(得分:1)

我同意@Fyodor Soikin。您应该在Defect类中使用原型FilterQuery。如果这不可行,您可以始终从界面中省略 ... AsDate 属性并将其实现为扩展。您必须将每个基于类的扩展的实现推迟到通用实现,或者如果您使用基于接口的扩展,则在使用该方法之前强制转换为接口。如果方法/属性很复杂,或者你使用的代码多于为每个类重新实现它们,那么前者可能才有意义。

public static class DefectExtensions
{
     public static DateTime SubmitDateAsDate( this IDefectProperties source )
     {
            return DateTime.Parse( source.SubmitDate );
     }

     public static void SetSubmitDateAsDate( this IDefectProperties source, DateTime date )
     {
           source.SubmitDate = date.ToString();
     }
}

答案 4 :(得分:1)

这是一个想法。而不是FilterQuery实现IDefectProperties,它的构造函数或搜索方法可以接受实现此接口的对象。

构造函数选项:

class FilterQuery{
    IDefectProperties defectProperties;
    FilterQuery(IDefectProperties dp){
        defectProperties=dp;
    }
}

使用搜索属性设置FilterQuery对象(而不是在FilterQuery中设置属性)并将其传递给FilterQuery。你可以使用一个Defect对象或从它继承的东西或其他东西(这个设计开启了很多可能性)这将使FIlterQuery更加连贯,只留下它负责搜索和取回结果。

答案 5 :(得分:0)

为什么不在实用程序类中实现SubmitDateAsDate并从每个类调用该实用程序?