I've seen plenty of examples of how to use generic Objects in C#, but can I have a generic property for a static object?
I have 2 distinct lists of Providers:
List<Providers> OldProviders
List<Providers> NewProviders
OldProviders has providers from the database, and NewProviders has providers the user has selected in the View. If any OldProviders aren't in NewProviders, I want to remove them from the database. If any NewProviders aren't in OldProviders, I want to add them to the database. Simple.
One problem: Provider has 2 properties that correspond to foreign keys important for comparison: StaffID and LicenseID (both integers) Depending on the choice the user makes, I only care about one of these IDs.
Currently I have 2 sets of helper methods which are completely identical (6 total helpers), except for whether they compare using StaffID or LicenseID. It technically works, but I don't want to maintain it.
Here's an example:
private bool DeleteOldStaffProviders(List<Provider> oldSelectedStaff, List<Provider> newSelectedStaff)
{
foreach (var oldSelected in oldSelectedStaff)
{
bool remove = newSelectedStaff.SingleOrDefault(n => n.StaffID == oldSelected.StaffID) == null;
if (remove)
{
//<remove from database, return false if failure>
}
}
return true;
}
Is there a way I can rewrite this method with a generic parameter reference? i.e.
newSelectedStaff.SingleOrDefault(n => n.T == oldSelected.T)
where T is either LicenseID or StaffID.
I've seen a lot of examples of people using LINQ and reflection for things kinda similar to this, but I can't seem to figure it out. If you could baby me through it, that would be appreciated.
Yes, use another parameter of type Func<Provider,int>
to act as the selector:
private bool DeleteOldStaffProviders(List<Provider> oldSelectedStaff, List<Provider> newSelectedStaff, Func<Provider,Provider,bool> selector)
{
foreach (var oldSelected in oldSelectedStaff)
{
bool remove = newSelectedStaff.SingleOrDefault(n => selector(n) == selector(oldSelected)) == null;
if (remove)
{
//<remove from database, return false if failure>
}
}
return true;
}
usage
DeleteOldStaffProviders(oldStaff, newStaff, x => x.StaffID);
DeleteOldStaffProviders(oldStaff, newStaff, x => x.LicenseID);
You could do it another way - but I think its more clunky. Pass in a Func<Provider,Provider,bool>
like this:
DeleteOldStaffProviders(oldStaff, newStaff, (o,n) => o.StaffID == n.StaffID);
And change a line to:
bool remove = newSelectedStaff.SingleOrDefault(n => selector(n,oldSelected))