Home > Net >  How to manipulate a list with a custom getter?
How to manipulate a list with a custom getter?

Time:04-06

I have a list that is stored as a serialized string in one of my tables (I'm using the Azure Data Tables SDK). That's why I have two properties, one as a string and other as a list that is ignored and only used within our code.

public string VisitedNodes { get; private set; } = JsonConvert.SerializeObject(new List<string>());

[IgnoreDataMember]
public List<string> VisitedNodesList
{
    get => JsonConvert.DeserializeObject<List<string>>(VisitedNodes);
    set => VisitedNodes = JsonConvert.SerializeObject(value);
}

However, I simply can't manipulate this list easily because methods like .AddRange or .Add won't work. If I need to change its values I have to create an auxiliary object

var aux = VisitedNodesList;
aux.Add("node1");
VisitedNodesList = aux;

As this isn't what I indented to do at first, I suspect I might be doing something wrong or that there's a better way to store serialized values in a entity.

CodePudding user response:

What about this?

public string VisitedNodes { get; private set; } = JsonConvert.SerializeObject(VisitedNodesList);

private List<String> _visitedNodeList = new List<String>(); 
[IgnoreDataMember]
public List<string> VisitedNodesList
{
    get => _visitedNodeList;
    set => _VisitedNodeList = value;
}




CodePudding user response:

If you can change type of VisitNodesList property, you can replace it to custom collection type inherited from Collection<T> with overloaded ***Item() methods.

Based on example from docs:

public class CollectionWithOnChangeAction<T> : Collection<T>
{
    public Action? OnChange { get; set; }

    protected override void InsertItem(int index, T item)
    {
        base.InsertItem(index, item);
        OnChange?.Invoke();
    }

    protected override void SetItem(int index, T item)
    {
        base.SetItem(index, item);
        OnChange?.Invoke();
    }

    protected override void RemoveItem(int index)
    {
        base.RemoveItem(index);
        OnChange?.Invoke();
    }

    protected override void ClearItems()
    {
        base.ClearItems();
        OnChange?.Invoke();
    }
}

And then use it like this:

public class SomeClass
{
    public string VisitedNodes { get; private set; } = JsonConvert.SerializeObject(new List<string>());

    [IgnoreDataMember] private CollectionWithOnChangeAction<string> _visitedNodesList;

    [IgnoreDataMember]
    public CollectionWithOnChangeAction<string> VisitedNodesList
    {
        get => _visitedNodesList;
        set
        {
            _visitedNodesList = value;
            _visitedNodesList.OnChange = OnChange;
            OnChange();
        }
    }

    public SomeClass()
    {
        VisitedNodesList = new CollectionWithOnChangeAction<string>();
    }

    private void OnChange()
    {
        VisitedNodes = JsonConvert.SerializeObject(VisitedNodesList);
    }
}

public class Tests
{
    [Fact]
    public void Test()
    {
        SomeClass someClass = new();

        someClass.VisitedNodesList.Add("node1");
        someClass.VisitedNodesList.Add("node2");
        someClass.VisitedNodesList.Add("node3");
        someClass.VisitedNodesList.Add("node4");
        Assert.Equal(JsonConvert.SerializeObject(new List<string> { "node1", "node2", "node3", "node4" }),
            someClass.VisitedNodes);

        someClass.VisitedNodesList.Insert(2, "insert node");
        Assert.Equal(JsonConvert.SerializeObject(new List<string>
        {
            "node1",
            "node2",
            "insert node",
            "node3",
            "node4"
        }), someClass.VisitedNodes);

        someClass.VisitedNodesList[4] = "set node";
        Assert.Equal(JsonConvert.SerializeObject(new List<string>
        {
            "node1",
            "node2",
            "insert node",
            "node3",
            "set node"
        }), someClass.VisitedNodes);

        someClass.VisitedNodesList.Remove("node2");
        Assert.Equal(JsonConvert.SerializeObject(new List<string> { "node1", "insert node", "node3", "set node" }),
            someClass.VisitedNodes);

        someClass.VisitedNodesList.RemoveAt(0);
        Assert.Equal(JsonConvert.SerializeObject(new List<string> { "insert node", "node3", "set node" }),
            someClass.VisitedNodes);

        someClass.VisitedNodesList = new CollectionWithOnChangeAction<string> { "new node1", "new node2" };
        Assert.Equal(JsonConvert.SerializeObject(new List<string> { "new node1", "new node2" }),
            someClass.VisitedNodes);
    }
}
  • Related