Можно ли легко и динамически украсить объект?
например, скажем, у меня есть 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 реализованы в библиотеках классов). Однако это все равно означает, что вам нужно изменить подписи в местах, где вы используете тип (что, скорее всего, не то, что вы хотите сделать, когда ищете декоратора).