How can I remove duplication between methods that differ only in type but use non-default constructors?
Hello I got a lot of methods (below 2 examples) that look almost exactly the same. The difference lies in the name of the JSON handler that is being processed, the type of the returned list, and the type of objects added to the list . I know these example methods still need some optimization in their body, but the point is to pass the return type and class type that currently needs this method and make it all work. If possible, I would like to avoid casting instead of calling method.
Method 1
public static List<Box> JsonToListOfBoxes(string data)
{
List<Box> ListOfBoxes = new List<Box>();
if(!string.IsNullOrEmpty(data))
{
JObject productsJson = JObject.Parse(data);
JToken jtkProduct;
jtkProduct = productsJson["boxes"];
if(jtkProduct != null)
if(jtkProduct.HasValues)
{
int childrenCount = productsJson["boxes"].Count();
for(int x = 0;x < childrenCount;x++)
ListOfBoxes.Add(new Box(productsJson["boxes"][x]));
}
}
return ListOfBoxes;
}
Method 2
public static List<Envelope> JsonToListOfEnvelopes(string data)
{
List<Envelope> ListOfEnvelopes = new List<Envelope>();
if(!string.IsNullOrEmpty(data))
{
JObject productsJson = JObject.Parse(data);
JToken jtkProduct;
jtkProduct = productsJson["envelopes"];
if(jtkProduct != null)
if(jtkProduct.HasValues)
{
int childrenCount = productsJson["envelopes"].Count();
for(int x = 0;x < childrenCount;x++)
ListOfEnvelopes.Add(new Envelope(productsJson["envelopes"][x]));
}
}
return ListOfEnvelopes;
}
source to share
You can do a general method when it dataName
should be "boxes" or "envelopes":
public static List<T> JsonToListOfBoxes<T>(string data, string dataName)
{
List<T> ListOfItems = new List<T>();
if (!string.IsNullOrEmpty(data))
{
JObject productsJson = JObject.Parse(data);
JToken jtkProduct;
jtkProduct = productsJson[dataName];
if (jtkProduct != null)
if (jtkProduct.HasValues)
{
int childrenCount = productsJson[dataName].Count();
for (int x = 0; x < childrenCount; x++)
ListOfItems.Add((T)Activator.CreateInstance(typeof(T), productsJson[dataName][x]));
}
}
return ListOfItems;
}
Usage example:
var list1 = JsonToListOfBoxes<Box>("dataString", "boxes");
var list2 = JsonToListOfBoxes<Envelope>("dataString", "envelopes");
source to share
With generics, you can change like this: (no parameterized generic constructor)
public static List<T> JsonToListOfEnvelopes<T>(string data, string searchString, Func<string, T> creator)
{
List<T> ListOfEnvelopes = new List<T>();
if (!string.IsNullOrEmpty(data))
{
JObject productsJson = JObject.Parse(data);
JToken jtkProduct;
jtkProduct = productsJson[searchString];
if (jtkProduct != null)
if (jtkProduct.HasValues)
{
int childrenCount = productsJson[searchString].Count();
for (int x = 0; x < childrenCount; x++)
ListOfEnvelopes.Add(creator(productsJson[searchString][x]));
}
}
return ListOfEnvelopes;
}
And you can call him
var result = JsonToListOfEnvelopes("data", "boxes", c => { return new Box(c); });
var result = JsonToListOfEnvelopes("data", "envelopes", c => { return new Envelope(c); });
source to share
I changed @msmolcic's logic a bit.
public static List<T> JsonToListOfBoxes<T>(string data)
{
List<T> ListOfItems = new List<T>();
string dataName = typeof(T) == typeof(Box) ? "boxes" : "envelopes";
//if there are many types one can try in below way..
// if (typeof(T) == typeof(Box))
// {
// dataName = "Box";
// }
// else if (typeof(T) == typeof(Envelope))
// {
// dataName = "envelopes";
// }
if (!string.IsNullOrEmpty(data))
{
JObject productsJson = JObject.Parse(data);
JToken jtkProduct;
jtkProduct = productsJson[dataName];
if (jtkProduct != null)
if (jtkProduct.HasValues)
{
int childrenCount = productsJson[dataName].Count();
for (int x = 0; x < childrenCount; x++)
ListOfItems.Add((T)Activator.CreateInstance(typeof(T), productsJson[dataName][x]));
}
}
return ListOfItems;
}
source to share