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

时间:2015-09-14 09:57:20

标签: c#

我正在使用一种方法来尝试迭代一个对象来获取所有对象的属性,其中一些是对象列表。

除了检查初始对象属性中的对象的部分外,这一切都有效。如果它找到了一个对象列表,我希望它迭代它们。

令人讨厌的是,我在{+ 1}}列表中列出了任何类型的内容。

我现在在VS中收到错误,因为null没有实例化,但它会在运行时。

下面是我用来尝试捕获正在解析的任何对象/列表的if语句。

我是走右路(环形交叉路口)还是做这个还是完全错了?

有问题的代码 - 如果语句空列表:

pt

发布创建方法:

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

发送电子邮件方式:

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

班级对象:

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

2 个答案:

答案 0 :(得分:3)

  

如果它找到了一个对象列表,我希望它迭代它们。

迭代时不需要list,最小可迭代类型为IEnumerable。实际上,您的if语句正在检查

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

那么为什么不在内部使用

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

编辑:看到这个,它有效,然后看看为什么你没有:

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

答案 1 :(得分:1)

也许你可以在if语句中尝试这样的事情吗?

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

此主题也可以为您提供帮助:How to get the type of T from a member of a generic class or method?