dynamically decorating objects in c#
is it possible to easily and dynamically decorate an object?
for example, lets say I have a List<PointF>
. this list is actually a plot of the sine function. I'd like to go through these points and开发者_Python百科 add a flag to each PointF of whether it's a peak or not.
but I don't want to create a new extended SpecialPointF or whatever, that has a boolean property.
judge me all you want for being lazy, but laziness is how awesome ideas are born (also bad ideas)
Edit: I'll accept boxing solutions as well as any interesting hack you can come up with. there's nothing really stopping me from deriving. I just want to know if there's a more fun way.
No, there's no way to do (specifically) what you're asking for.
Assuming you're using C# 3.0+, you can use anonymous types to do this, assuming that you don't want to expose the information outside of your function.
var decoratedList = sourceList.Select(pt => new
{
IsPeak = GetIsPeak(pt),
Point = pt
}).ToList();
This will give you a new List<T>
object. This may very well not solve your problem, since you cannot extend this outside of a single function call and you're creating a new list rather than modifying an existing one, but hopefully this helps.
If there's a way you can calculate that per point, you don't need to add a flag to it, you can use an extension method without having to extend it.
Something like PointF.isPeak();
It works something like:
public static class Extensions
{
public static bool isPeak (this PointF p)
{
do crazy math...
return result;
}
}
And voilà, you have your calculation in your PointF class.
By the way, the public static class has to be in the outermost scope, cant be nested.
It might be possible to do this using the new dynamic keyword and ExpandoObject
construct in C# 4.0, but I don't have firsthand experience with it yet. As I understand it was created to solve this exact problem easily, so you can say
dynamic something = new ExpandoObject();
something.Anything = "whatever you want";
I believe it is possible to extend existing types dynamically, but it might require creating a new subclass, which would defeat the whole purpose of the exercise.
An almost-identical solution can be created using extension methods. The ExpandoObject
is internally implemented as a Dictionary
, but it adds the classy native syntax.
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;
}
}
No it's not possible.
Closest will be just creating a
var decorationData = new Dictionary <Object, bool>
and then saving your values in there. No need to extend the type directly. You can even use an extension method to access the stored data which will then look like it is a direct property of the object.
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;
}
}
And adding to your edit:
You could also solve this with a generic type that contains just the decoration data and the referenced type (In the same way as Nullable types are implemented in the class libraries). However that still means you have to change the signatures at the places you use the type (which is likely not what you want to do when looking for decorator).
精彩评论