Search code examples
c#jsonabstract-classgeneric-list

How do I create a generic List using abstract class?


I have a Json class "GetAllDevices()". My JSON response consists of an Array/List of objects, where each object has the below common properties.

public class GetAllDevices
{
    [JsonProperty("_id")]
    public string Id { get; set; }

    [JsonProperty("name")]
    public string Name { get; set; }

    [JsonProperty("type")]
    public string Type { get; set; }

    [JsonProperty("actions")]
    public Action[] Actions { get; set; }

    public class Action
    {
        public string _id { get; set; }
        public Action_Def action_def { get; set; }
    }

    public class Action_Def
    {
        public string _id { get; set; }
        public string name { get; set; }
    }
}

I want to create 2 generic lists containing all the above properties based on its "type". lstfoo1 List contains all the properties(_id, name type and actions) where type="foo1". Similarly, lstfoo2 is a List which contains the above properties where type="foo2".

What I have done so far:

string strJson=getJSON();
Foo1 lstfoo1=new Foo1();
Foo2 lstfoo2=new Foo2();
List<Foo1> foo1list= lstfoo1.GetDeviceData(strJson);
List<Foo2> foo2list = lstfoo2.GetDeviceData(strJson);


public class AllFoo1: GetAllDevices
{
}

public class AllFoo2: GetAllDevices
{
}

public abstract class HomeDevices<T>
{
    public string type { get; set; }
    public string _id { get; set; }
    public List<AllFoo1> lstfoo1{ get; set; }
    public List<AllFoo2> lstfoo2{ get; set; }
    public abstract List<T> GetDeviceData(string jsonResult);
}

public class Foo1: HomeDevices<AllFoo1>
{
    public Foo1()
    {
        type = "foo1";
    }

    public override List<AllFoo1> GetDeviceData(string jsonResult)
    {
        var lst =Newtonsoft.Json.JsonConvert.DeserializeObject<List<AllFoo1>>(jsonResult);
        var lst1 = lst.Where(x => x.Type.Equals(type)).ToList();
        return lst1;
    }
}

public class Foo2: HomeDevices<AllFoo2>
{
    public Foo2()
    {
        type = "foo2";
    }

    public override List<AllFoo2> GetDeviceData(string jsonResult)
    {
        var lst = Newtonsoft.Json.JsonConvert.DeserializeObject<List<AllFoo2>>(jsonResult);
        var lst1 = lst.Where(x => x.Type.Equals(type)).ToList();
        return lst1;
    }
}

My question is, is there an easier way to do this using abstract classes? Can I directly convert my "GetAllDevices" class into an abstract class and inherit it and deserialize into it and create a generic list?


Solution

  • It should be simple enough to move the implementation of method GetDeviceData() to the base class.

    For this to work, you will need to add a constraint on T so the compiler knows a bit more about the base type. You will also need to implement a constructor to populate the concrete type's type string you use around. This is a necessary measure to ensure the value is always populated as it is used for comparison in the method in question:

    public abstract class HomeDevices<T> where T: GetAllDevices
    {
        public HomeDevices(string concreteType)
        {
            type = concreteType;
        }
    
        public string type { get; set; }
        public string _id { get; set; }
        public List<AllFoo1> lstfoo1 { get; set; }
        public List<AllFoo2> lstfoo2 { get; set; }
    
        //This method is now generic and works for both.
        public List<T> GetDeviceData(string jsonResult)
        {
            var lst = Newtonsoft.Json.JsonConvert.DeserializeObject<List<T>>(jsonResult);
            var lst1 = lst.Where(x => x.Type.Equals(type)).ToList();
            return lst1;
        }
    }
    

    I hope that helps.