How to access Properties of a class from a Generic Method - C#

前端 未结 5 596
-上瘾入骨i
-上瘾入骨i 2020-12-06 16:49

I have a three class which is having following properties

Class A
{
    public int CustID { get; set; }
    public string Name{ get; set; }
}

Class B
{
             


        
相关标签:
5条回答
  • 2020-12-06 17:14

    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 ;
        });
    }
    
    0 讨论(0)
  • 2020-12-06 17:16

    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 )
        });
    }
    
    0 讨论(0)
  • 2020-12-06 17:21

    Another possibility would be to use System.Reflection.

    1. Get the PropertyInfo from the given type T with the name of the property

    2. 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.

    0 讨论(0)
  • 2020-12-06 17:21

    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
        }
    
    0 讨论(0)
  • 2020-12-06 17:25

    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)
         });
     }
    
    0 讨论(0)
提交回复
热议问题