简体   繁体   English

当对泛型使用反射时,PropertyInfo List为null

[英]PropertyInfo List is null when using reflection with generics

I am using a method to try and iterate through an object to get all of the object's properties, some of which are lists of objects. 我正在使用一种方法尝试遍历对象以获取对象的所有属性,其中一些是对象列表。

This all works except for the part where I check for objects within the initial object's properties. 除了我在初始对象的属性内检查对象的那一部分之外,所有其他方法均有效。 If it finds a list of objects I want it to iterate through them. 如果找到对象列表,我希望它遍历它们。

Annoyingly, I'm getting null on my list of whatever type. 烦人的是,我在任何类型的列表上都得到null

I'm now getting an error in VS because pt isn't instantiated, but it would be at run time. 我现在在VS中遇到错误,因为pt未实例化,但是会在运行时出现。

Below is the if statement I'm using to try and catch whatever object/List is being parsed. 下面是我用来尝试捕获正在解析的任何对象/列表的if语句。

Am I going the right (roundabout) way or doing this or is this completely wrong? 我是沿着正确的(回旋处)方式还是这样做还是完全错误?

Problematic Code - if statement null list: 有问题的代码-if语句空列表:

public static string DeconstructLists<T>(T obj, string body)
        {
            Type type = obj.GetType();
            PropertyInfo[] properties = type.GetProperties();

            foreach (PropertyInfo property in properties)
            {
                if (property.PropertyType == typeof(string) || property.PropertyType == typeof(int) || property.PropertyType == typeof(bool))
                    body += property.Name + " = " + property.GetValue(obj, null) + Environment.NewLine;

                else
                {
                    if (typeof(IEnumerable).IsAssignableFrom(property.PropertyType))
                    {
                        //null list exception
                        var list = (IEnumerable)property.GetValue(obj, null);
                        foreach (var item in list)
                        {
                            DeconstructLists(item, body);
                        }

                        // stack overflow exception
                        //var props = property.PropertyType.GetGenericArguments()[0];

                        //foreach (var p in props.GetProperties())
                        //{
                        //    DeconstructLists(p, body);
                        //}
                    }
                }
            }
            return body;
        }

Post create method: 发布创建方法:

public ActionResult Create(Company cmp)
        {
            if (ModelState.IsValid)
            {
                db.companys.Add(cmp);
                db.SaveChanges();
                // send email
                SendEmail(cmp);
                return RedirectToAction("Thankyou", "Home", new { form="ASN" });
            }
            return View(cmp);
        }

Send email method: 发送电子邮件的方法:

public static void SendEmail(Company cm)
        {
            string _body = "";
            string _subject = "ASN Form Request";

            _body = DeconstructLists<Company>(cm, _body);

            using (SmtpClient msgClient = new SmtpClient())
            {
                msgClient.EnableSsl = false;
                msgClient.DeliveryMethod = SmtpDeliveryMethod.Network;
                msgClient.UseDefaultCredentials = false;
                msgClient.Credentials = new NetworkCredential
                    {                    
                        UserName = "",
                        Password = ""
                    };
                msgClient.Host = "";
                msgClient.Port = 0;

                using (MailMessage msg = new MailMessage())
                {
                    msg.To.Add(""); // to add
                    msg.From = new MailAddress("");// from add
                    msg.Subject = _subject;
                    msg.Body = _body;
                    // preparing the message to be sent
                    msgClient.Send(msg);
                }
            }
        }

Class objects: 类对象:

public class Company
    {
        public int companyId { get; set; }
        public string name { get; set; }
        public string telephone { get; set; }
        public string regNumber { get; set; }
        public virtual IList<Asn> asns { get; set; }
        public virtual IList<Contact> contacts { get; set; }
    }
    public class Contact
    {
        public int contactId { get; set; }
        public int companyId { get; set; }
        public Company company { get; set; }
        public string name { get; set; }
        public string telephone { get; set; }
    }
public class Asn
    {
        public int asnId { get; set; }
        public int companyId { get; set; }
        public Company company { get; set; }
        public bool userBehalf { get; set; }
        public bool something { get; set; }
    }

If it finds a list of objects I want it to iterate through them. 如果找到对象列表,我希望它遍历它们。

You don't need a list for iteration, the minimum iteratable type is IEnumerable . 您不需要迭代list ,最小可迭代类型为IEnumerable In fact your if statement is checking just that 实际上,您的if语句正在检查

if (typeof(IEnumerable).IsAssignableFrom(property.PropertyType))
{
    // ...
}

So why not just using inside 那为什么不只是在内部使用

var list = (IEnumerable)property.GetValue(obj, null);
foreach (var item in list)
{
    DeconstructLists(item, body);
}

EDIT: See this, it works, then see why yours does not: 编辑:看到它,它工作,然后看看为什么你的不:

using System;
using System.Collections;
using System.Collections.Generic;

namespace Tests
{
    class Test
    {
        static void Main(string[] args)
        {
            var company = new Company
            {
                companyId = 1,
                name = "ACME",
            };
            company.asns = new List<Asn>
            {
                new Asn { asnId = 1, companyId = company.companyId, company = company  },
                new Asn { asnId = 2, companyId = company.companyId, company = company  },
            };
            company.contacts = new List<Contact>
            {
                new Contact { contactId = 1, companyId = company.companyId, company = company, name = "Contact1" },
                new Contact { contactId = 2, companyId = company.companyId, company = company, name = "Contact2" }
            };
            var body = DeconstructLists(company, "");
        }
        public static string DeconstructLists<T>(T obj, string body)
        {
            var type = obj.GetType();
            var properties = type.GetProperties();
            foreach (var property in properties)
            {
                if (property.PropertyType == typeof(string) || property.PropertyType == typeof(int) || property.PropertyType == typeof(bool))
                    body += property.Name + " = " + property.GetValue(obj, null) + Environment.NewLine;
                else
                {
                    if (typeof(IEnumerable).IsAssignableFrom(property.PropertyType))
                    {
                        body = body + property.Name + ": {" + Environment.NewLine;
                        var list = (IEnumerable)property.GetValue(obj, null);
                        foreach (var item in list)
                        {
                            body = body + item.GetType().Name + ": {" + DeconstructLists(item, "") + "}" + Environment.NewLine;
                        }
                        body = body + "}" + Environment.NewLine;
                    }
                }
            }
            return body;
        }
    }
    public class Company
    {
        public int companyId { get; set; }
        public string name { get; set; }
        public string telephone { get; set; }
        public string regNumber { get; set; }
        public virtual IList<Asn> asns { get; set; }
        public virtual IList<Contact> contacts { get; set; }
    }
    public class Contact
    {
        public int contactId { get; set; }
        public int companyId { get; set; }
        public Company company { get; set; }
        public string name { get; set; }
        public string telephone { get; set; }
    }
    public class Asn
    {
        public int asnId { get; set; }
        public int companyId { get; set; }
        public Company company { get; set; }
        public bool userBehalf { get; set; }
        public bool something { get; set; }
    }
}

Maybe you could try something like this in your if statement ? 也许您可以在if语句中尝试类似的方法?

var genericType = property.PropertyType.GetGenericArguments()[0];
foreach (var prop in genericType.GetProperties())
{
    DeconstructLists(prop, body);
}

This topic may also help you: How to get the type of T from a member of a generic class or method? 本主题还可以为您提供帮助: 如何从泛型类或方法的成员中获取T的类型?

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

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