我有一个细分类,它是树中的一个节点。没有Tree
类。该树仅由段组成。
public abstract class Segment
{
public List<Segment> Descendants { get; } => new List<Segment> Descendants;
public abstract SegmentVisual VisualRepresentation { get; }
}
SegmentVisual
是用于将细分绘制到屏幕上的类。这两个类都是抽象的,因为我有不同类型的线段,并且每个线段的绘制方式都不同。这是
SegmentVisual
的样子:public abstract class SegmentVisual : DrawingVisual
{
protected SegmentVisual(Segment owner){
this.Owner = owner;
}
public Segment Owner { get; }
public List<SegmentVisual> Descendants { get; } = new List<SegmentVisual>();
public void Redraw()
{
this.RedrawItself();
foreach (SegmentVisual visual in this.Visuals)
{
visual.Redraw();
}
}
public abstract void RedrawItself();
}
与细分一样,视觉对象也具有后代,因此可以将单个视觉对象添加到屏幕上以绘制自身及其所有后代
这是一个实现:
public class LineSegment : Segment
{
public LineSegment()
{
this.VisualRepresentation = new LineSegmentVisual(this);
}
public override SegmentVisual VisualRepresentation { get; }
public Pen Stroke { get; set; }
}
。
public class LineSegmentVisual : SegmentVisual
{
public LineSegmentVisual(LineSegment owner) // Resharper suggests this can be Segment base class
: base(owner)
{
}
public override void RedrawItself()
{
using (DrawingContext ctx = this.RenderOpen())
{
var owner = (LineSegment)this.Owner;
ctx.DrawLine(owner.Stroke, this.Owner.Position, this.Owner.ControlPointPos);
}
}
}
我的问题是最后一堂课。您可以看到ReSharper的建议。而且我一直都不太满意投降。如果必须在其他地方检索所有者,则必须沮丧地重新获得Stroke属性。
如果我将
SegmentVisual
泛型SegmentVisual<T>
的所有者设为T
,则会引入新的障碍,因为现在SegmentVisual
只能包含SegmentVisual<T>
的后代,而事实并非如此,因为我希望它包含任何类型的SegmentVisual
,我只希望所有者强类型化。我只希望
SegmentVisual
能够对应于特定的类,以便其Owner
属性被强类型化。我似乎无法弄清楚。 最佳答案
您可以使用new
在子类中声明强类型的Owner
:
public class LineSegmentVisual : SegmentVisual
{
new LineSegment Owner { get { return (LineSegment)base.Owner; } }
public LineSegmentVisual(Segment owner)
: base(owner)
{
}
public override void RedrawItself()
{
using (DrawingContext ctx = this.RenderOpen())
{
var owner = this.Owner;
ctx.DrawLine(owner.Stroke, this.Owner.Position, this.Owner.ControlPointPos);
}
}
}
这样,每次调用
base.Owner
时都会强制使用this.Owner
,但是至少您要避免重复代码。第二种方法是使用继承。使用基本功能声明
SegmentVisual
abstract class SegmentVisual
{
public List<SegmentVisual> Descendants { get; private set; }
...
}
和
OwnedSegmentVisual
与强类型所有者abstract class OwnedSegmentVisual<TOwner>: SegmentVisual where TOwner: Segment
{
public TOwner Owner { get; private set; }
protected OwnedSegmentVisual(TOwner owner)
{
Owner = owner;
}
}
Owner
可以在子类中使用,而无需强制转换,并且常用功能只能使用SegmentVisual
。第三种方法是使用泛型协方差,但是您必须为类型声明接口:
public class Program
{
public static void Main()
{
var sv = new LineSegmentVisual();
sv.Descendants = new List<ISegmentVisual<Segment>> { new SquareSegmentVisual() };
}
}
abstract class Segment {}
class LineSegment : Segment {}
class SquareSegment: Segment {}
interface ISegmentVisual<out TOwner>
{
TOwner Owner { get; }
List<ISegmentVisual<Segment>> Descendants { get; }
}
class LineSegmentVisual : ISegmentVisual<LineSegment>
{
public LineSegment Owner { get; set; }
public List<ISegmentVisual<Segment>> Descendants { get; set; }
}
class SquareSegmentVisual : ISegmentVisual<SquareSegment>
{
public SquareSegment Owner { get; set; }
public List<ISegmentVisual<Segment>> Descendants { get; set; }
}
希望这会有所帮助。