这是我的代码:
var fields = type.GetFields(BindingFlags.Public | BindingFlags.Instance);
foreach (FieldInfo field in fields)
{
//some code
}
var props = type.GetProperties();
foreach (PropertyInfo prop in props)
{
//exact same code
}
我知道我可以创建一个我可以调用两次的函数,但我想做的事情(如果可能的话)是单foreach
。这样的事情(是的,代码不起作用。如果有效,我不会问这个问题!):
var fields = type.GetFields(BindingFlags.Public | BindingFlags.Instance);
var props = type.GetProperties();
foreach (PropertyInfo prop in fields && PropertyInfo prop in props)
{
//some code
}
我真的觉得有办法,即使我知道我的解决方案远非可编辑:(
谢谢你的帮助!
答案 0 :(得分:3)
如果您对MemberInfo类(它是FieldInfo和PropertyInfo的基础)公开的属性没有问题,那么您可以执行以下操作:
var fields = type.GetFields(BindingFlags.Public | BindingFlags.Instance).Cast<MemberInfo>();
var props = type.GetProperties().Cast<MemberInfo>();
var fieldsAndProperties = fields.Union(props);
foreach (MemberInfo mi in fieldsAndProperties)
{
...
}
答案 1 :(得分:1)
如果MemberInfo
中公开的功能在循环中对您足够,那么您可以在同一个数组或其他可枚举上连接两个字段和属性,并只迭代一次。
这是可能的,因为FieldInfo
和PropertyInfo
都继承自MemberInfo
类。
示例代码:
var fields = typeof(DateTime).GetFields(
BindingFlags.Public | BindingFlags.Instance);
var properties = typeof(DateTime).GetProperties(
BindingFlags.Public | BindingFlags.Instance);
var all = fields.Cast<MemberInfo>().Concat(properties.Cast<MemberInfo>());
foreach (MemberInfo mi in all)
{
//some code
}
答案 2 :(得分:1)
将它们放入一个循环中:
foreach (MemberInfo member in fields.Cast<MemberInfo>().Concat(props))
{
//I'm 100% sure this isn't what you want
//because you need to set value here
//in this case, you still need to check if member is a FieldInfo/PropertyInfo
//and then convert it before you set the values
}
实际上,在这里使用两个循环可能更好。首先,代码看起来更清晰,因为它们正在做不同的事情,一个设置字段值,另一个设置属性。其次,寄存器缓存可能有助于使您的程序比一个循环快一点。
答案 3 :(得分:0)
这种迭代正在失去字段和属性的顺序。 例如。
class Test
{
public String tests { get; set; }
public int testi;
}
如果GetFields获得第一名 - 我们得到&#34; testi&#34;作为第一个成员,通过GetProperies我们得到&#34;测试&#34;。 联盟可能会将它们合并,但订单不会被保留。
有没有办法获取字段和属性并保留它们的顺序?
答案 4 :(得分:0)
我建议遵循以下步骤遍历对象并记录对象信息。
public static string ObjectToString(object obj)
{
var sb = new StringBuilder();
try
{
sb.AppendLine(obj.GetType().Name);
foreach (var prop in obj.GetType().GetProperties())
{
sb.AppendLine(string.Format("{0} Property Name: {1}; Value: [{2}]; Type: {3}", "--->", prop.Name, prop.GetValue(obj, null)?.ToString(), prop.PropertyType?.FullName));
}
foreach (var fld in obj.GetType().GetFields())
{
if (!fld.FieldType.Namespace.Equals("System", StringComparison.InvariantCultureIgnoreCase) && fld.GetValue(obj) != null)
{
ObjectToString(fld.GetValue(obj), sb);
}
else
{
sb.AppendLine(string.Format("{0} Field Name: {1}; Value: [{2}]; Type: {3}", "--->", fld.Name, fld.GetValue(obj)?.ToString(), fld.FieldType?.FullName));
}
}
}
catch (Exception ex)
{
sb.AppendLine("---> Exception in ObjectToString: " + ex.Message);
}
return sb.ToString();
}
public static string ObjectToString(object obj, StringBuilder sb, int depth = 1)
{
try
{
sb.AppendLine(string.Format("{0}{1} {2}", (depth==2?"----":""),"--->", obj.GetType().Name));
foreach (var prop in obj.GetType().GetProperties())
{
sb.AppendLine(string.Format("{0} Property Name: {1}; Value: [{2}]; Type: {3}", "------->", prop.Name, prop.GetValue(obj, null)?.ToString(), prop.PropertyType?.FullName));
}
foreach (var fld in obj.GetType().GetFields())
{
//we want to avoid stake overflow and go only one more depth
if (!fld.FieldType.Namespace.Equals("System", StringComparison.InvariantCultureIgnoreCase) && fld.GetValue(obj) != null && depth < 2)
{
ObjectToString(fld.GetValue(obj), sb, 2);
}
else
{
sb.AppendLine(string.Format("{0} Field Name: {1}; Value: [{2}]; Type: {3}", "------->", fld.Name, fld.GetValue(obj)?.ToString(), fld.FieldType?.FullName));
}
}
}
catch (Exception ex)
{
sb.AppendLine("-------> Exception in ObjectToString: depth(" + depth + ") " + ex.Message);
}
return sb.ToString();
}
答案 5 :(得分:0)
通过反射访问成员属性的一个问题是速度慢。 有一个小型库,可以使用一些动态生成的访问器代码FastMember来很好,快速地完成这项工作。要使用它迭代所有公共字段和属性,您需要运行如下这样的简单循环:
string postData;
using (var stream = await request.Content.ReadAsStreamAsync())
{
stream.Seek(0, SeekOrigin.Begin);
using (var sr = new StreamReader(stream))
{
postData = await sr.ReadToEndAsync();
}
}
当您需要设置可以像这样完成的任何对象实例的字段或属性的值时:
var ta = TypeAccessor.Create(typeof(MyClass));
foreach (var prop in ta.GetMembers())
{
Console.WriteLine(prop.Name);
}