Страницы

Поиск по вопросам

пятница, 20 декабря 2019 г.

Добавить поле к существующему классу (Attached Properties)

#c_sharp


Есть класс Line c полями Begin, End.
Теперь нужно чтобы у класса Line была толщина.
Реализую с помощью методов расширения GetDepth и SetDepth.
Как это можно сделать? 

namespace Geometry   
{
    public class Line
    {
        public Point Begin;
        public Point End;
    }
} 

namespace GeometryPaint
{
    public static class SegmentExtension
    {
        public static int GetDepth (this Line line)
           {
               //TODO
           }
        public static void SetDepth (this Line line, int depth)
           {
               //TODO
           }
    }

    public static class SegmentExtension
    {
        static void Main()
           {
               var lineOne = new Line { Begin = new Point(0,0), End = new Point(3,3)};
               var lineTwo = new Line { Begin = new Point(4,2), End = new Point(7,9)};
               lineOne.SetDepth(5);
               lineTwo.SetDepth(32);
               int depthLineTwo = lineTwo.GetDepth();
               int depthLineOne = lineOne.GetDepth();
           }
    }
}

    


Ответы

Ответ 1



То, что вы хотите, называется Attached Properties. В C# нет родного (на уровне синтаксиса) механизма их реализации. Но в стандартной библиотеке есть класс ConditionalWeakTable, который позволяет хранить значения "дополнительных" свойств, не продлевая при этом жизнь объектов-ключей. Реализация attached properties через него будет выглядеть примерно так: using System.Runtime.CompilerServices; namespace Geometry { public static class SegmentExtensions { // TValue должен быть reference type, так что костыль в виде каста к object private readonly static ConditionalWeakTable _depthValues = new ConditionalWeakTable(); public static int GetDepth(this Line line) { return (int)_depthValues.GetValue(line, (l) => 0); } public static void SetDepth(this Line line, int depth) { _depthValues.Remove(line); // возможно, затрайкетчить в случае работы из нескольких потоков _depthValues.Add(line, depth); } } public static class Startup { static void Main() { var lineOne = new Line { Begin = new Point ( 0, 0 ), End = new Point ( 3, 3 ) }; var lineTwo = new Line { Begin = new Point ( 4, 2 ), End = new Point ( 7, 9 ) }; lineOne.SetDepth(5); lineTwo.SetDepth(32); int depthLineTwo = lineTwo.GetDepth(); int depthLineOne = lineOne.GetDepth(); } } public class Line { public Point Begin; public Point End; } public class Point { private int v1; private int v2; public Point(int v1, int v2) { this.v1 = v1; this.v2 = v2; } } }

Комментариев нет:

Отправить комментарий