Динамически украшающие объекты в С#

Можно ли легко и динамически украсить объект?

например, скажем, у меня есть List<PointF>. этот список фактически представляет собой график функции синуса. Я хотел бы пройти через эти точки и добавить флаг для каждой точки F, будь то пик или нет.

но я не хочу создавать новый расширенный SpecialPointF или что-то еще, имеющее свойство boolean.

судите обо всем, что вы хотите, чтобы быть ленивым, но лень - это то, как рождаются удивительные идеи (также плохие идеи)

Изменить: я приму решение для бокса, а также любой интересный хак, который вы можете придумать. мне ничего не мешает. Я просто хочу узнать, есть ли более увлекательный способ.

Ответ 1

Если есть способ, который вы можете вычислить для каждой точки, вам не нужно добавлять к ней флаг, вы можете использовать расширение без расширения.

Что-то вроде PointF.isPeak();

Он работает примерно так:

public static class Extensions
{
    public static bool isPeak (this PointF p)
    {
        do crazy math...

        return result;
    }
}

И у вас есть ваш расчет в вашем классе PointF.

Кстати, общедоступный статический класс должен находиться в самой внешней области, не может быть вложенной.

Ответ 2

Нет, нет способа сделать (конкретно) то, о чем вы просите.

Предполагая, что вы используете С# 3.0+, вы можете использовать анонимные типы для этого, предполагая, что вы не хотите раскрывать информацию вне вашей функции.

var decoratedList = sourceList.Select(pt => new 
                    { 
                        IsPeak = GetIsPeak(pt), 
                        Point = pt 
                    }).ToList();

Это даст вам новый объект List<T>. Это может очень сильно не решить вашу проблему, поскольку вы не можете расширять это за пределами одного вызова функции, и вы создаете новый список, а не изменяете существующий, но, надеюсь, это помогает.

Ответ 3

Возможно, это будет возможно с помощью нового dynamic и ExpandoObject конструкции в С# 4.0, но я не знаю, У меня есть опыт работы с ним. Насколько я понимаю, он был создан для решения этой точной проблемы, так что вы можете сказать

dynamic something = new ExpandoObject();
something.Anything = "whatever you want";

Я полагаю, что можно динамически распространять существующие типы, но для этого может потребоваться создание нового подкласса, который бы превзошел все цели упражнения.

Почти тождественное решение может быть создано с использованием методов расширения. ExpandoObject внутренне реализуется как Dictionary, но он добавляет собственный классный синтаксис.

class Program {

   static void Main(string[] args)
   {
      PointF p = new PointF(0, 0);

      p.SetFlag(true);

      if (p.GetFlag())
         Console.WriteLine("win");
   }

}

public static class Extensions
{
   private static Dictionary<PointF, bool> flags = new Dictionary<PointF, bool>();
   public static bool GetFlag(this PointF key)
   {
      return flags[key];
      //OR return flags.ContainsKey(key) ? flags[key] : false;
   }

   public static void SetFlag(this PointF key, bool val)
   {
      flags[key] = val;
   }
}

Ответ 4

Нет, это невозможно.

Ближе всего будет только создание

var decorationData = new Dictionary <Object, bool>

а затем сохраните свои значения там. Не нужно распространять тип напрямую. Вы даже можете использовать метод расширения для доступа к сохраненным данным, который будет выглядеть так, как будто это прямое свойство объекта.

public static class PointFPeakExtensions
{ 
    private static var decorationData = new Dictionary <PointF, bool>

    public static bool IsPeak (this PointF point) 
    { 
        return decorationData[point];
    } 
    public static void SetPeak (this PointF point, bool isPeak) 
    { 
        decorationData[point] = isPeak;
    } 
} 

И добавив в ваше редактирование:

Вы также можете решить это с помощью универсального типа, который содержит только данные украшения и ссылочный тип (точно так же, как типы Nullable реализованы в библиотеках классов). Однако это все равно означает, что вам нужно изменить подписи в местах, где вы используете тип (что, скорее всего, не то, что вы хотите сделать, когда ищете декоратора).