Jan Daliba
Jan Daliba

Reputation: 35

How to address specific element in list

I want to create "list of list of list". It should be:

Group (has a list of Members)

Member (has a Name and list of Properties)

Property (has Name and Value)

What I want is to have a possibility to add Property into Member (specified by its name) inside defined Group. Someting like this:

membersgroup.AddNewMember(memberXYZ);
...
membersgroup.memberXYZ.AddProperty(nameXYZ, valueXYZ).

I have trouble achieving this using list... I found class Hashable, but I am not sure if this is usable... and cannot make it works too...

Thank for any suggestion :)

Upvotes: 0

Views: 642

Answers (4)

fqhv
fqhv

Reputation: 1201

Likely the best solution is to use the C# class Dictionary - as suggested by zetawars, or a custom class - as suggested by Zohar Peled, or some mix of the two - as suggested by gandalf.


However, in order to use syntax similar to what is requested in the question...

membersgroup.AddNewMember(memberXYZ);
...
membersgroup.memberXYZ.AddProperty(nameXYZ, valueXYZ).

You can abuse ExpandoObject and Action, and do something awesome like this:

dynamic membersgroup = new ExpandoObject();

var getNewMemberObject = new Func<dynamic>(() =>
{
    dynamic memberObject = new ExpandoObject();
    var addPropertyAction = new Action<string, string>((propertyName, propertyValue) => 
    {
        ((IDictionary<string, object>)memberObject).Add(propertyName, propertyValue);
    });

    memberObject.AddProperty = addPropertyAction;

    return memberObject;
});

var addNewMemberAction = new Action<string>((memberName) =>
{
    ((IDictionary<string, object>)membersgroup).Add(memberName, getNewMemberObject());
});

membersgroup.AddNewMember = addNewMemberAction;

string memberXYZ = nameof(memberXYZ);
string nameXYZ = nameof(nameXYZ);
string valueXYZ = nameof(valueXYZ);

// look we did it!
membersgroup.AddNewMember(memberXYZ);
membersgroup.memberXYZ.AddProperty(nameXYZ, valueXYZ);

// and it actually works
var actualValue = membersgroup.memberXYZ.nameXYZ;
Console.WriteLine(actualValue); // "valueXYZ"

(for science of course)

Upvotes: 0

gandalf
gandalf

Reputation: 470

public class Group
{
public Group()
{
    Members = new List<Member>();
}

public IEnumerable<Member> Members { get; set; }
}

public class Member
{
public Member()
{
    Properties = new Dictionary<string, string>();
}

public string Name { get; set; }
IDictionary<string, string> Properties { get; set; }
}

The dictionary can take a key and a value, and the key should be unique. You can also create a class property if you want to add another thing beside the name and the value

Upvotes: 0

Zohar Peled
Zohar Peled

Reputation: 82514

I would use indexers.

Here's a partial implementation:

class Group 
{
    private List<Member> _members;

    public string this
    {
        get
        {
            return _members.Find(m => m.Name == value);
        }
        // You can also implement set here if you want...
    }
}

class Member
{
    private List<Property> _properties;

    public string Name {get;set;}

    public string this
    {
        get
        {
            return _properties.Find(m => m.Name == value);
        }
    }
}

class Property
{
    public string Name {get;set;}

    public string Value {get;set;}
}

And the usage:

var g = new Group();
g[memberName][propertyName].Value = someValue;

Note: This implementation is partial! it still needs constructor logic and any other logic you might need.

Upvotes: 0

zetawars
zetawars

Reputation: 1081

Well, I suggest you create a custom class instead of your approach. But otherwise you can use a Dictionary.

var properties = new Dictionary<string, string>();
properties.Add("Prop1", "Value");

var members = new Dictionary<string, Dictionary<string, string>>();
members.Add("Member1", properties);

var group = new Dictionary<string, Dictionary<string, Dictionary<string, string>>>();
group.Add("GroupName", members);

Upvotes: 1

Related Questions