This Is My Models :
public class Result1
{
public string Price { get; set; }
public string Id { get; set; }
}
public class Result2
{
public string firstName { get; set; }
public string lastName { get; set; }
public string Id { get; set; }
}
public class JsonResult1
{
public List<Product> ProductLists { get; set; }
}
public class JsonResult2
{
public List<User> UserLists { get; set; }
}
And This is My First And Second Methods
public async Task<List<Result1>> GetFirstMethod(string id, string a)
{
var info = JsonConvert.DeserializeObject<JsonResult1>(a);
var mylist = new List<Result1>();
foreach (var item in info.ProductLists)
{
mylist.Add(new Result1()
{
Price = item.Price,
Id = item.ID
});
}
return mylist;
}
public async Task<List<Result2>> GetSecondMethod(string id, string a)
{
var info = JsonConvert.DeserializeObject<JsonResult2>(a);
var mylist = new List<Result2>();
foreach (var item in info.UserLists)
{
mylist.Add(new Result2()
{
firstName = item.FirstName,
lastName = item.LastName,
Id = item.ID
});
}
return mylist;
}
//And the third method and the fourth method and...
Each method has different models...
How to make a generic method for All the above methods??
The main problem is in the mapping part inside the list...
Is it even possible to do something like this?
This is the most probably convoluted answer imaginable, but you can use a dictionary to keep delegates to map between the three different types:
public class Mapping {
public static readonly Dictionary<(Type,Type), Mapping> RegisteredMappings = new();
public Func<object,IEnumerable<object>> enumerate;
public Func<object,object> map;
public static void Register<T,M,R>(Func<T, IEnumerable<M>> enumerateFunc, Func<M, R> mappingFunc) where T : class where M : class where R : class {
RegisteredMappings.Add((typeof(T), typeof(R)), new Mapping {
enumerate = (object input) => enumerateFunc((T) input),
map = (object input) => mappingFunc((M) input),
});
}
}
public static List<R> Get<T,R>(string id, string a) {
if (!Mapping.RegisteredMappings.TryGetValue((typeof(T), typeof(R)), out Mapping mapping)) {
throw new ArgumentException($"No mapping exists between {typeof(T).Name} and {typeof(R).Name}");
}
T info = JsonConvert.DeserializeObject<T>(a);
List<R> list = new();
foreach (var item in mapping.enumerate(info)) {
list.Add((R) mapping.map(item));
}
return list;
}
Example usage:
public static void Main()
{
// Example JSON for JsonResult1 (Product) and JsonResult2 (User)
string productJson = "{\"ProductLists\": [{\"Price\": \"100.00\", \"ID\": \"XYZ\"},{\"Price\": \"50.00\", \"ID\": \"ABC\"}]}";
string userJson = "{\"UserLists\": [{\"FirstName\": \"Mark\", \"LastName\": \"B.\", \"ID\": \"XYZ\"},{\"FirstName\": \"Joseph\", \"LastName\": \"S.\", \"ID\": \"ABC\"}]}";
// Register the mapping from JsonResult1 -> Result1 and JsonResult2 -> Result2 (using the Product/User classes as an intermediary)
Mapping.Register<JsonResult1, Product, Result1>(EnumerateProducts, MapProduct);
Mapping.Register<JsonResult2, User, Result2>(EnumerateUsers, MapUser);
// Example usage
List<Result1> productResults = Get<JsonResult1, Result1>("unused", productJson);
Console.WriteLine(string.Join(',', productResults.Select(product => product.Price)));
// -> 100.00,50.00
List<Result2> userResults = Get<JsonResult2, Result2>("unused", userJson);
Console.WriteLine(string.Join(',', userResults.Select(user => user.firstName)));
// -> Mark,Joseph
}
public static IEnumerable<Product> EnumerateProducts(JsonResult1 jr1) => jr1.ProductLists;
public static Result1 MapProduct(Product p) {
return new Result1 {
Price = p.Price,
Id = p.ID,
};
}
public static IEnumerable<User> EnumerateUsers(JsonResult2 jr2) => jr2.UserLists;
public static Result2 MapUser(User u) {
return new Result2 {
firstName = u.FirstName,
lastName = u.LastName,
Id = u.ID
};
}
This way you only need to register each mapping once on boot, and then you never have to reference them again. Simply calling the function with the input/result types specified will work.