简体   繁体   English

如何从泛型方法访问类的属性-C#

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

I have a three class which is having following properties 我有一个具有以下属性的三班

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

Class B
{
    public int CustID { get; set; }
    public string Age { get; set; }
}

I created one generic method which accepts all these classes. 我创建了一个接受所有这些类的通用方法。

public void ProceesData<T>(IList<T> param1, string date1)
{
    Parallel.ForEach(T, (currentItem) =>
    {
       // I want to aceess CustID property of param1 and pass that value to another function
        GetDetails(CustID );
        RaiseRequest<T>(param1);
    });
}

CustID property is present in Both classes(ie in Class A& Class B).How can i access CustID property in this generic method ? 两个类都存在CustID属性(即A类和B类)。如何在此通用方法中访问CustID属性? Can anyone help on this 任何人都可以帮忙吗

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)
     });
 }

Another possibility would be to use System.Reflection . 另一种可能性是使用System.Reflection

  1. Get the PropertyInfo from the given type T with the name of the property 获取PropertyInfo从给定类型T与属性的名称

  2. with that PropertyInfo you can use GetValue to get the corresponding value of that property. 通过该PropertyInfo您可以使用GetValue获取该属性的相应值。

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: 正如古斯曼(Gusman)所建议的,您可以通过在循环之前获取一次PropertyInfo来加快速度:

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. 不要按原样运行程序,而是单独运行每个测试。

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 )
    });
}

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
    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM