I am trying to use generics to reduce my codebase, but ran into this situation. I can't seem to successfully create a google query that expresses what I am trying to do.
In essence I am passing in a Generic to make a List<T>
and then pass that List<T>
into a function that requires a List<SpecificClass>
My JSONUser class
public class JSONUser
{
public string DocumentId { get; set; }
[JsonProperty(PropertyName = "UserName", Required = Required.Always)]
public string UserName { get; set; }
[JsonProperty(PropertyName = "FirstName", Required = Required.AllowNull)]
public string FirstName { get; set; }
[JsonProperty(PropertyName = "LastName", Required = Required.AllowNull)]
public string Lastname { get; set; }
}
Assume there is a class JSONCompany with company like fields.
Main Code:
static void CollectUserData()
{
boolean j = GetJSON<JSONUser>();
boolean k = GetJSON<JSONCompany>();
...
}
static boolean GetJSON<T>()
{
...
// Get the JSON in a List
List<T> oJSON = CallRest<T>();
// Now depending on the type passed in, call a different
// Process Function which expects a List<JSONUser> or
// List<JSONCompany> parameter
if (typeof(T) == typeof(JSONUser))
{
boolean result = ProcessUser(oJSON);
...
}
else if (typeof(T) == typeof(JSONCompany))
{
boolean result = ProcessCompany(oJSON);
...
}
...
}
public boolean ProcessUser(List<JSONUser> JSONList)
{
...
}
public boolean ProcessCompany(List<JSONCompany> JSONList)
{
...
}
Everything is good until I call the ProcessUser(oJSON);
It says there is no method to accept the Generic. When I try to cast it, it says
Cannot Covert Type
System.Collection.Generic.List<T>
toSystem.Collection.Generic.List<JSONUser>
Hopefully this is clear.
If ProcessUser
et al does not require a list and can work with just an IEnumerable<T>
then you can simplify it a bit:
public boolean ProcessUser(IEnumerable<JSONUser> JSONList)
{
...
}
public boolean ProcessCompany(IEnumerable<JSONCompany> JSONList)
{
...
}
Then just call it with:
boolean result = ProcessUser(oJSON.Cast<JSONUser>());
otherwise you could create a new list:
boolean result = ProcessUser(oJSON.Cast<JSONUser>().ToList());
which may be fine if you're just iteerating/modifying the objects in the list and not the list itself. (adding/removing/sorting/etc.)
As OP has indicated that the Process functions need to operate on the lists, here is a second answer to complement my first answer. Based on feedback from OP, this assumes that the purpose of ProcessUser/ProcessCompany was really meant to bulk-upload the list of users/companies to a database, which I will assume to be SQL. In this case, JSONUser and JSONCompany (and his other classes) would likely require different SQL calls to function correctly.
Thus, this code demonstrates iterating over the generic list, still using Interface on the base class to define how that object gets written to the database, and yet still not relying on typeof(T).
public interface IInsertToSql
{
void InsertToSql(SqlCommand cmd);
}
public class JSONUser : IInsertToSql
{
public string UserID { get; set; }
public void InsertToSql(SqlCommand cmd)
{
cmd.CommandText = "sp_insertJsonUser";
cmd.Parameters.AddWithValue("@jsonUserId", UserID);
// More parameters
cmd.ExecuteNonQuery();
}
}
public class JSONCompany : IInsertToSql
{
public string CompanyID { get; set; }
public void InsertToSql(SqlCommand cmd)
{
cmd.CommandText = "sp_insertJsonCompany";
cmd.Parameters.AddWithValue("@jsonCompanyId", CompanyID);
// More parameters....
cmd.ExecuteNonQuery();
}
}
void Main()
{
List<JSONUser> users = GetJSON<JSONUser>();
List<JSONCompany> companies = GetJSON<JSONCompany>();
BulkUpload(users);
BulkUpload(companies);
}
static void BulkUpload<T>(List<T> list)
where T: IInsertToSql
{
using(SqlConnection conn = new SqlConnection(""))
{
conn.Open();
foreach(T t in list)
{
using (SqlCommand cmd = conn.CreateCommand()) t.InsertToSql(cmd);
}
}
}
static List<T> GetJSON<T>()
{
// OP's code to get the list of items, instead of...
return new List<T>();
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With