使用反射将对象投射到自定义类型列表

时间:2019-06-12 11:43:58

标签: c# list generics reflection casting

我有以下情况:

我有一个包含列表的复合对象,我想向其传递“路径”,例如-Result.CustomerList.Name

结果是一个对象,其中包含“客户列表”,但也包含许多其他不同类型的列表。在这种情况下,我想了解客户的名字。

到目前为止我有什么

    private static object GetPropertyValue(this object obj, string propertyPath)
    {
        var fullPath = propertyPath.Split('.');
        for (int i = 0; i <= fullPath.Length - 1; i++)
        {
            if (obj == null) { return null; }
            var part = fullPath[i];

            Type type = obj.GetType();
            PropertyInfo propInfo = type.GetProperty(part);

            if (propInfo == null)
            {
                //if its a list
                if (obj.GetType().GetInterfaces().Any(
                    k => k.IsGenericType
                    && k.GetGenericTypeDefinition() == typeof(IEnumerable<>)))
                {
                    //get list generic argument
                    var argumentType = obj.GetType().GetGenericArguments()[0];

                   //cast obj to List of argumentType


                }
                else return null;
            }

            obj = propInfo.GetValue(obj, null);
        }

        return obj;
    }

我无法获取语法或如何强制转换为List或List无效或List

我不知道自己缺少什么或怎么做。

编辑:: 在运行时,可能是CustomerList,AddressList或PaymentList或任何其他类型的列表。我需要一种能够在运行时检索任何类型的列表中的属性值的方法。

EDIT2 :: 结果对象示例

public class SearchResults
{
    public List<Customer> Customers { get; set; }
    public List<Payment> Payments { get; set; }
    public List<Address> Addresses{ get; set; }
    public int totalCount { get; set; }
    public bool success { get; set; }


}

public class Customer
{
    public string Name { get; set; }
    public long Id { get; set; }
}

public class Payment
{
    public string BankName{ get; set; }
    public long Id { get; set; }
}

因此,像Result.Payments.BankName这样的路径应该返回我任何东西。问题是我无法使该方法访问任何列表都具有通用性。

2 个答案:

答案 0 :(得分:0)

我认为通过将对象强制转换为IEnumerable来枚举对象可能会更容易:

var objCollection = obj as IEnumerable;
if (objCollection == null)
{
    // this is not a collection
}
else
{
    // just enumerate the objCollection.
}

答案 1 :(得分:0)

我设法通过动态方式解决了问题

private static object GetPropertyValue(this object obj, string propertyPath)
    {
        var fullPath = propertyPath.Split('.');
        for(int i = 0; i <= fullPath.Length - 1; i++)
        {
            if (obj == null) { return null; }
            var part = fullPath[i];

            Type type = obj.GetType();
            PropertyInfo propInfo = type.GetProperty(part);

            if (propInfo == null)
            {
                //if its a list
                if (obj.GetType().GetInterfaces().Any(
                    k => k.IsGenericType
                    && k.GetGenericTypeDefinition() == typeof(IEnumerable<>)))
                {
                    //convert to IList from object
                    var genericList = (IList)obj;

                    //returned the desired property
                    return genericList.Cast<dynamic>()
                        .First(p => p.PropertyName.ToLower().Equals(part.ToLower()))
                        .PropertyValue;
                }
                else return null;
            }

            obj = propInfo.GetValue(obj, null);
        }

        return obj;
    }

此方法现在适用于对象中的每个列表。