While Marcin Juraszek solution is great, I just want to expand his answer just a little bit with dynamic
sugar. It's not the fact, that this solution will fit your need, but just consider it as an example. I will make Directory<T>
generic, so you can use whatever type for value
(note that due to dynamic nature I have one cast in implementation (T)value
)
class Directory<T> : DynamicObject
{
private T Value;
private Dictionary<string, Directory<T>> SubDirectories;
public Directory()
{
SubDirectories = new Dictionary<string, Directory<T>>();
}
public override bool TryGetMember(GetMemberBinder binder, out Object result)
{
if (!SubDirectories.ContainsKey(binder.Name))
SubDirectories[binder.Name] = new Directory<T>();
result = SubDirectories[binder.Name];
return true;
}
public override bool TrySetMember(SetMemberBinder binder, Object value)
{
if (!SubDirectories.ContainsKey(binder.Name))
SubDirectories[binder.Name] = new Directory<T>();
SubDirectories[binder.Name].Value = (T)value;
return true;
}
public override string ToString()
{
return Value.ToString();
}
}
And now you can use dynamic
feature, available from C# 4.0
dynamic dir = new Directory<string>();
dir.foo = "Foo Value";
dir.foo.bar = "Bar Value";
dir.foo.bar.baz = "baz value";
dir.foo.bar.Lol = "Lol value";
Console.WriteLine(dir.foo.bar.Lol); //will print Lol value
Console.WriteLine(dir.foo.bar.baz); //will print baz value
which is:
Foo Foo Value
|__Bar Bar Value
|__Baz baz value
|__Lol Lol value
you can also override TryGetIndex and TrySetIndex so that you can pass complex strings, which can't be used as properties in C#