-1

I've worked with API's that had what appeared to be instances of methods within other entities, and I haven't been able to figure out how to recreate this for myself. For instance, if I have a class called "House", and there were different doors in that house, and I wanted to put a window in one of the doors, the code to work with the instance would look something like this:

House myHouse = New House;
myHouse.Rooms("living room").Doors("front").PlaceWindow("frosted four pane");

I hope my representation makes sense. I've been living in VB.Net for months, and we're just starting to switch back to C#. I am really just curious about the This.This.This.This aspect.

I'd like to have an object that is this easy to use and manipulate, and I can only place properties and methods within a single class with my current knowledge. I just don't know what to search for in the search engines to figure out how to make this kind of class (or whatever type of compilation it is). If anyone could steer me in the right direction, it would help tremendously.

Jason Aller
  • 3,541
  • 28
  • 38
  • 38

2 Answers2

2

There are some dangers with type of approach; see Law of Demeter.

However, if you wish to do this, you simply create each object with the child-objects you wish to have.

For your example you would create these:

public class House
{
    private readonly List<Room> _rooms = new List<Room>();

    public Room Rooms(string roomName)
    {
        return _rooms.Single(x => x.Name == roomName);
    }

    public void AddRoom(string roomName)
    {
        _rooms.Add(new Room { Name = roomName });
    }
}

public class Room
{
    private readonly List<Door> _doors = new List<Door>();

    public string Name { get; set; }

    public Door Doors(string doorName)
    {
        return _doors.Single(x => x.Name == doorName);
    }

    public void AddDoor(string doorName)
    {
        _doors.Add(new Door { Name = doorName });
    }
}

public class Door
{
    private readonly List<Window> _windows = new List<Window>();

    public string Name { get; set; }

    public Window Windows(string windowName)
    {
        return _windows.Single(x => x.Name == windowName);
    }

    public void PlaceWindow(string windowName)
    {
        _windows .Add(new Window { Name = windowName }); 
    }
}

public class Window
{
    public string Name { get; set; }
}
Silas Reinagel
  • 4,155
  • 1
  • 21
  • 28
0

Here is an alternative modular approach to building multi-tiered objects more easily.

public abstract class NamedObject
{
    public string Name { get; set; }
}

public class ComponentCollection<T> where T : NamedObject
{
    private readonly List<T> _components = new List<T>();

    public T this[string name]
    {
        get { return Get(name); }
    }

    public T Get(string name)
    {
        return _components.Single(x => x.Name == name);
    }

    public void Add(T component)
    {
        _components.Add(component);
    }

    public void Remove(string name)
    {
        _components.RemoveAll(x => x.Name == name);
    }
}

This makes components easier to create and maintain:

public class House
{
    public readonly ComponentCollection<Room> Rooms = new ComponentCollection<Room>();
}

public class Room : NamedObject
{
    public readonly ComponentCollection<Door> Doors = new ComponentCollection<Door>();
}

public class Door : NamedObject
{
    public readonly ComponentCollection<Window> Windows = new ComponentCollection<Window>();
}

public class Window : NamedObject
{
}

The change to call syntax is fairly minor:

[TestMethod]
public void House_AddFrostedPaneWindowToLivingRoomFrontDoor_WindowExists()
{
    var myHouse = new House();
    myHouse.Rooms.Add(new Room { Name = "Living Room" });
    myHouse.Rooms["Living Room"].Doors.Add(new Door { Name = "Front" });
    myHouse.Rooms["Living Room"].Doors["Front"].Windows.Add(new Window { Name = "Frosted Four Pane" });

    var window = myHouse.Rooms["Living Room"].Doors["Front"].Windows["Frosted Four Pane"];

    Assert.IsNotNull(window);
}
Silas Reinagel
  • 4,155
  • 1
  • 21
  • 28
  • I just wanted to thank everyone for their help. All of the insight is fully appreciated. I've been reading through the links too, and it will definitely be a treat to play around with this. Happy coding everybody! – Mike Warner Mar 18 '15 at 18:52