I have a three class which is having following properties
Class A
{
public int CustID { get; set; }
public string Name{ get; set; }
}
Class B
{
If you can't introduce interface or base class on your existing classes, another approach is to use dynamic:
public void ProceesData<T>(IList<T> param1, string date1)
{
Parallel.ForEach(param1, (currentItem) =>
{
dynamic obj = currentItem;
int custId = obj.CustID ;
});
}
Inheritance will work
public abstract class ABBase
{
public int CustID { gete; set; }
}
public class A : ABBase
{
public string Name { get; set; }
}
public class B : ABBase
{
public string Age { get; set; }
}
Then rather than a generic method use
public void ProcessData(IList<ABBase> param1, string date)
{
Parallel.ForEach(T, (currentItem) =>
{
GetDetails(CustID )
});
}
Another possibility would be to use System.Reflection
.
Get the PropertyInfo
from the given type T
with the name of the property
with that PropertyInfo
you can use GetValue
to get the corresponding value of that property.
Here is a small test programm to exemplify this:
public class ClassA
{
public int CustID { get; set; }
public string Name { get; set; }
}
public class ClassB
{
public int CustID { get; set; }
public string Age { get; set; }
}
public static void ProceesData<T>(IList<T> param1, string date1)
{
Parallel.ForEach(param1, (currentItem) =>
{
// I want to aceess CustID property of param1 and pass that value to another function
var value = typeof(T).GetProperty("CustID").GetValue(currentItem);
Console.WriteLine("Value: " + value);
});
}
public static void Main(string[] args)
{
List<ClassA> test = new List<ClassA>();
test.Add(new ClassA { CustID = 123 });
test.Add(new ClassA { CustID = 223 });
test.Add(new ClassA { CustID = 323 });
ProceesData<ClassA>(test, "test");
}
EDIT
To make it a little more universal you could just pass the parameter name into the method:
public static void ProceesData<T>(IList<T> param1, string date1, string parameter)
{
Parallel.ForEach(param1, (currentItem) =>
{
// I want to aceess CustID property of param1 and pass that value to another function
var value = typeof(T).GetProperty(parameter).GetValue(currentItem);
Console.WriteLine("Value: " + value);
});
}
Now you can decide what parameter you want to use:
ProceesData<ClassA>(test, "test", "Name");
or
ProceesData<ClassB>(test, "test", "Age");
As suggested by Gusman you could speed up a little by getting the PropertyInfo
just once before the loop:
PropertyInfo pi = typeof(T).GetProperty(parameter);
Parallel.ForEach(param1, (currentItem) =>
{
// I want to aceess CustID property of param1 and pass that value to another function
var value = pi.GetValue(currentItem);
Console.WriteLine("Value: " + value);
});
EDIT
Apparently performance seems to be an issue for you. So here is a comparison. You can try it on your own if you have a minute to wait. If we measure on the access time of the property:
public static void ProceesDataD<T>(IList<T> param1, string date1)
{
Parallel.ForEach(param1, (currentItem) =>
{
dynamic obj = currentItem;
int custId = obj.CustID;
});
}
public static void ProceesData<T>(IList<T> param1, string date1) where T : ICust
{
Parallel.ForEach(param1, (currentItem) =>
{
var value = currentItem.CustID;
});
}
public static void ProceesData<T>(IList<T> param1, string date1, string parameter)
{
PropertyInfo pi = typeof(T).GetProperty(parameter);
Parallel.ForEach(param1, (currentItem) =>
{
var value = pi.GetValue(currentItem);
});
}
public static void Main(string[] args)
{
List<ClassA> test = new List<ClassA>();
List<A> testA = new List<A>();
Stopwatch st = new Stopwatch();
for (int i = 0; i < 10000; i++)
{
test.Add(new ClassA { CustID = 123, Name = "Me" });
testA.Add(new A { CustID = 123, Name = "Me" });
}
st.Start();
ProceesData<ClassA>(test, "test", "CustID");
st.Stop();
Console.WriteLine("Reflection: " + st.ElapsedMilliseconds);
st.Restart();
ProceesData<A>(testA, "test");
st.Stop();
Console.WriteLine("Interface: " + st.ElapsedMilliseconds);
st.Restart();
ProceesDataD<ClassA>(test, "test");
st.Stop();
Console.WriteLine("Dynamic: " + st.ElapsedMilliseconds);
}
Disclaimer: use the code passages to measure the time only one at the time. Do not run the program as it is but each single test on it's own.
dynamic
should fix this issue, don't cast or go around in circles..
List<T> products = new List<T>();
foreach (dynamic prod in products)
{
prod.ShopCategoryID = 1 ; // give you access to props
}
Introduce interface:
interface ICust
{
public int CustID { get;}
}
class A : ICust
{
public int CustID { get; set; }
public string Name{ get; set; }
}
class B : ICust
{
public int CustID { get; set; }
public string Age { get; set; }
}
public void ProceesData<T>(IList<T> param1, string date1) where T : ICust
{
Parallel.ForEach(param1, (currentItem) =>
{
GetDetails(currentItem.CustID)
});
}