Type-safe Dictionary for various types
Your suggestion is not really type-safe as you can still pass a key of the wrong type. Therefore I would just use a normal (string) key. But I would add a generic TryGet method which takes account of the type. The setter needs not to be generic. 

static class DictionaryExtensions
{
    public static T Get&lt;T&gt;(this IDictionary&lt;string, object&gt; dictionary, string key)
    {
        return (T)dictionary[key];
    }

    public static bool TryGet&lt;T&gt;(this IDictionary&lt;string, object&gt; dictionary,
                                 string key, out T value)
    {
        object result;
        if (dictionary.TryGetValue(key, out result) &amp;&amp; result is T) {
            value = (T)result;
            return true;
        }
        value = default(T);
        return false;
    }

    public static void Set(this IDictionary&lt;string, object&gt; dictionary,
                           string key, object value)
    {
        dictionary[key] = value;
    }
}


You can then use the dictionary like this.

int age = 20;
dictionary.Set("age", age);

// ...

age = dictionary.Get&lt;int&gt;("age");

// or the safe way
if (dictionary.TryGet("age", out age)) {
    Console.WriteLine("The age is {0}", age);
} else {
    Console.WriteLine("Age not found or of wrong type");
}


Note that the compiler can infer the generic type when using TryGet.



UPDATE

In despite of my suggestion above, I must agree that your solution is elegant. Here is another suggestion which is based on your solution but which encapsulates the dictionary instead of providing a key. Well, it acts as wrapper and as key at the same time

public class Property&lt;T&gt;
{
    Dictionary&lt;object, object&gt; _dict;

    public Property (Dictionary&lt;object, object&gt; dict)
    {
        _dict = dict;
    }

    public T Value {
        get { return (T)_dict[this]; }
        set { _dict[this] = value; }
    }
}


Alternatively, a string key could be provided in the Property's constructor.

You can use it like this

private static readonly Dictionary&lt;object, object&gt; _properties = 
    new Dictionary&lt;object, object&gt;();
private static readonly Property&lt;int&gt; _age = new Property&lt;int&gt;(_properties);

...

_age.Value &gt; 18
_age.Value = age