The C# team has previously considered adding extension properties, events, etc. to C#.
Per Eric Lippert:
http://blogs.msdn.com/b/ericlippert/archive/2009/10
You're looking for the ConditionalWeakTable class.
** WHOLE ANSWEr EDITED ** The properties are kept in a dictionary that uses weak reference to the objects as keys, and a dictionay with string-object pairs to store the properties and their values.
To set, get or delete properties for an object, the object is search in the weak references in the dictionary.
There could be two ways to dispose of the non-used properties:
I've included an optional using block in the sample code, so that you can debug and see how the Dispose calls the RemoveProperties
extension method. This is of course optional, and the method would be called when the object is GC'ed.
Working sample of the idea, using WeakReference, static Dictionaries and IDisposable.
using System;
using System.Collections.Generic;
using System.Linq;
namespace ConsoleApplication3
{
class Program
{
static void Main(string[] args)
{
using (PropertyLessClass plc = new PropertyLessClass())
{
plc.SetProperty("age", 25);
plc.SetProperty("name", "John");
Console.WriteLine("Age: {0}", plc.GetProperty("age"));
Console.WriteLine("Name: {0}", plc.GetProperty("name"));
}
Console.ReadLine();
}
}
}
public class PropertyLessClass : IDisposable
{
public void Dispose()
{
this.DeleteProperties();
}
}
public static class PropertyStore
{
private static Dictionary<WeakReference, Dictionary<string, object>> store
= new Dictionary<WeakReference, Dictionary<string, object>>();
public static void SetProperty(this object o, string property, object value)
{
var key = store.Keys.FirstOrDefault(wr => wr.IsAlive && wr.Target == o);
if (key == null)
{
key = new WeakReference(o);
store.Add(key, new Dictionary<string, object>());
}
store[key][property] = value;
}
public static object GetProperty(this object o, string property)
{
var key = store.Keys.FirstOrDefault(wr => wr.IsAlive && wr.Target == o);
if (key == null)
{
return null; // or throw Exception
}
if (!store[key].ContainsKey(property))
return null; // or throw Exception
return store[key][property];
}
public static void DeleteProperties(this object o)
{
var key = store.Keys.FirstOrDefault(wr => wr.IsAlive && wr.Target == o);
if (key != null)
{
store.Remove(key);
}
}
}