简体   繁体   English

提取类型的列表属性 <T> 使用反射

[英]Extracting a list property of type <T> using Reflection

I have an object that contains many lists of other objects. 我有一个包含许多其他对象列表的对象。 I will provide a simple example. 我将提供一个简单的示例。

public class BaseApplicationData
{
    public long Id { get; set; }
}
public class Phone : BaseApplicationData
{
    public string PhoneType { get; set; }
    public string Number { get; set; }
    public string Extension { get; set; }
}
public class Employer : BaseApplicationData
{
    public double Salary { get; set; }
    public string Name { get; set; }
    public string EmployementType { get; set; }
}
public class Applicant : BaseApplicationData
{
    public string Name { get; set; }
    public string EmailAddress { get; set; }
    public List<Phone> PhoneNumbers { get; set; }
    public List<Employer> Employers { get; set; }
}

In the actual code I'm working with, there are a lot more of these lists. 在我正在使用的实际代码中,有很多这样的列表。 During the processing, we need to be able to perform CRUD actions for each of these lists. 在处理过程中,我们需要能够对这些列表中的每一个执行CRUD操作。 The process is the same for each list. 每个列表的过程相同。 So, rather than write a set of CRUD methods for each list type, it occurred to me that I could use generics and / or reflection to accomplish these actions for each list. 因此,我没有为每个列表类型编写一组CRUD方法,而是想到可以使用泛型和/或反射为每个列表完成这些操作。

So I created a method that does this but my results are not what I was expecting. 因此,我创建了一个可以做到这一点的方法,但结果却出乎意料。 Using the example objects above, I created an applicant object and added an Employer object to it. 使用上面的示例对象,我创建了一个申请人对象,并向其添加了一个雇主对象。 (This was to simulate a list with data already in it.) I then called my method (shown below). (这是模拟其中已有数据的列表。)然后,我调用了我的方法(如下所示)。

public long CreatePropertyValue<T>(Applicant applicant, T data, string propertyName)
{
    long newId = 0;
    var listproperty = applicant.GetType().GetProperty(propertyName);
    // Here is the problem, even with data in the list, listData.Count is always 0.
    List<T> listData = listproperty.GetValue(applicant, null) as List<T>;
    // psuedo code
    if list is null, create a new list
    assign a new Id value to object data (parameter)
    Add the data item to the list
    update the property of the applicant object with the updated list
    return newId;
}

A call to the method would look something like this. 对该方法的调用看起来像这样。 test.CreatePropertyValue(applicant, emp, "Employers"); test.CreatePropertyValue(申请人,emp,“雇主”);

When I call this method with no data in a list, I get null on the value as expected. 当我在列表中没有数据的情况下调用此方法时,按预期值将为null。 When I call this with data in the list already, the value of listData is a list of the correct type but with zero items in the list. 当我已经用列表中的数据调用它时,listData的值是正确类型的列表,但列表中的项为零。 Looking at listproperty.PropertyType.GetGenericArguments() I can see the actual items in the list. 查看listproperty.PropertyType.GetGenericArguments()我可以看到列表中的实际项目。 I want to be able to get the collection of listData based on the propertyName and type T then be able to add my T data item to the list and save it back. 我希望能够基于propertyName获取listData的集合并键入T,然后能够将T数据项添加到列表中并保存回去。 Similarly, I'll need to be able to update, delete, and return the list as well. 同样,我还需要能够更新,删除和返回列表。

I've looked at several questions on the site but none of them explain to me why my list contains 0 items when I use getvalue on the property. 我看过网站上的几个问题,但是没有一个问题向我解释为什么当我在属性上使用getvalue时为什么我的列表包含0个项目。

I would appreciate any help you can provide. 我会很感激您能提供的任何帮助。

Thanks 谢谢

UPDATE : Silly me, I was creating the array and the object but not adding the object to the array. 更新 :愚蠢的我,我在创建数组和对象,但没有将对象添加到数组中。 Nothing to see here, move along. 这里没什么好看的,离开。

Maybe, try to use lambda: 也许,尝试使用lambda:

    public void Test1()
    {
        var app = new Applicant();

        CreatePropertyValue(app, new Phone(), a => a.PhoneNumbers, (a, v) => a.PhoneNumbers = v);
        CreatePropertyValue(app, new Employer(), a => a.Employers, (a, v) => a.Employers = v);
    }

    public static long CreatePropertyValue<T>(Applicant applicant, T data, Func<Applicant, List<T>> getter, Action<Applicant, List<T>> setter)
        where T : BaseApplicationData
    {
        long newId = 0;

        var list = getter(applicant); //get list
        if (list == null) //check it
        {
            list = new List<T>();
            data.Id = newId;
            list.Add(data); //add new data
            setter(applicant, list); //set new list
        }
        return newId;
    }

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

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