我有以下课程:
Defect
- 表示可在数据库中找到的一种数据FilterQuery
- 提供了一种通过设置简单布尔过滤器来查询数据库的方法 Defect
和FilterQuery
都实现了相同的界面:IDefectProperties
。此接口指定数据库中的特定字段。不同的类具有返回Defect
个实例列表的方法。使用FilterQuery
,您可以为IDefectProperties
的一部分实现的特定属性指定一些过滤器,然后运行查询并返回Defect
个实例的列表。
我的问题是,我最终在FilterQuery
和Defect
中实现了完全相同的一些属性。这两个本质上是不同的类,它们只是共享一些相同的属性。例如:
public DateTime SubmitDateAsDate
{
get { return DateTime.Parse(SubmitDate); }
set { SubmitDate = value.ToString(); }
}
这是IDefectProperties
所需的属性,取决于其他属性SubmitDate
,该属性返回string
而不是DateTime
。现在SubmitDate
在Defect
和FilterQuery
中的实现方式不同,但SubmitDateAsDate
完全相同。有没有办法可以仅在SubmitDateAsDate
和Defect
将FilterQuery
和FilterQuery
作为属性进行定义? Defect
和{{1}}已经从两个不同的类继承,我认为无论如何共享一个祖先是没有意义的。我也愿意接受有关我的设计的建议。
答案 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并从每个类调用该实用程序?