[英]PropertyInfo List is null when using reflection with generics
我正在使用一种方法尝试遍历对象以获取对象的所有属性,其中一些是对象列表。
除了我在初始对象的属性内检查对象的那一部分之外,所有其他方法均有效。 如果找到对象列表,我希望它遍历它们。
烦人的是,我在任何类型的列表上都得到null
。
我现在在VS中遇到错误,因为pt
未实例化,但是会在运行时出现。
下面是我用来尝试捕获正在解析的任何对象/列表的if语句。
我是沿着正确的(回旋处)方式还是这样做还是完全错误?
有问题的代码-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;
}
发布创建方法:
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);
}
}
}
类对象:
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; }
}
如果找到对象列表,我希望它遍历它们。
您不需要迭代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; }
}
}
也许您可以在if语句中尝试类似的方法?
var genericType = property.PropertyType.GetGenericArguments()[0];
foreach (var prop in genericType.GetProperties())
{
DeconstructLists(prop, body);
}
本主题还可以为您提供帮助: 如何从泛型类或方法的成员中获取T的类型?
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.