C# 循环类型的GetFields和GetProperties?
这是我的密码:C# 循环类型的GetFields和GetProperties?,c#,foreach,propertyinfo,C#,Foreach,Propertyinfo,这是我的密码: 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 } 我知道我可以创建一个可以调
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
。类似这样的事情(是的,代码不起作用。如果它起作用,我不会问这个问题!)
我真的觉得有一种方法,即使我知道我的解决方案远不是可编译的:(感谢您的帮助!如果
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
}
var fields=typeof(DateTime).GetFields(
BindingFlags.Public | BindingFlags.Instance);
var properties=typeof(DateTime).GetProperties(
BindingFlags.Public | BindingFlags.Instance);
var all=fields.Cast().Concat(properties.Cast());
foreach(所有成员信息mi)
{
//一些代码
}
如果您对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)
{
...
}
var fields=type.GetFields(BindingFlags.Public | BindingFlags.Instance).Cast();
var props=type.GetProperties().Cast();
var fieldsAndProperties=fields.Union(props);
foreach(字段和属性中的MemberInfo mi)
{
...
}
要将它们放入一个循环中:
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
}
foreach(fields.Cast().Concat(props)中的MemberInfo成员)
{
//我百分之百肯定这不是你想要的
//因为您需要在这里设置值
//在这种情况下,您仍然需要检查成员是否为FieldInfo/PropertyInfo
//然后在设置值之前对其进行转换
}
实际上,在这里使用两个循环可能更好。首先,代码看起来更清晰,因为它们在做不同的事情,一个设置字段值,另一个用于属性。其次,寄存器缓存可能有助于使程序比一个循环快一点。Hmmm
这种迭代是失去了字段和属性的顺序。
例如
If GetFields If get first-我们得到“testi”作为第一个成员M,通过GetProperties我们得到“tests”。
工会可能会合并他们,但秩序并没有得到维护
有什么方法可以获取字段和属性并保持它们的顺序吗?我建议按照下面的方法遍历对象并记录对象信息
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();
}
公共静态字符串ObjectToString(objectobj)
{
var sb=新的StringBuilder();
尝试
{
sb.AppendLine(obj.GetType().Name);
foreach(obj.GetType().GetProperties()中的var prop)
{
sb.AppendLine(string.Format(“{0}属性名:{1};值:[{2}];类型:{3}”,“-->”,prop.Name,prop.GetValue(obj,null)?.ToString(),prop.PropertyType?.FullName));
}
foreach(obj.GetType().GetFields()中的变量fld)
{
如果(!fld.FieldType.Namespace.Equals(“System”,StringComparison.InvariantCultureIgnoreCase)和&fld.GetValue(obj)!=null)
{
ObjectToString(fld.GetValue(obj),sb);
}
其他的
{
sb.AppendLine(string.Format(“{0}字段名:{1};值:[{2}];类型:{3}”,“-->”,fld.Name,fld.GetValue(obj)?.ToString(),fld.FieldType?.FullName));
}
}
}
捕获(例外情况除外)
{
sb.AppendLine(“-->ObjectToString中的异常:“+ex.Message”);
}
使某人返回字符串();
}
公共静态字符串ObjectToString(对象obj,StringBuilder sb,int-depth=1)
{
尝试
{
sb.AppendLine(string.Format(“{0}{1}{2}”,(depth==2?”——:“),“-->”,obj.GetType().Name));
foreach(obj.GetType().GetProperties()中的var prop)
{
sb.AppendLine(string.Format(“{0}属性名:{1};值:[{2}];类型:{3}”,“---->”,prop.Name,prop.GetValue(obj,null)?.ToString(),prop.PropertyType?.FullName));
}
foreach(obj.GetType().GetFields()中的变量fld)
{
//我们希望避免桩溢出,只需再深入一层
如果(!fld.FieldType.Namespace.Equals(“System”,StringComparison.InvariantCultureIgnoreCase)和&fld.GetValue(obj)!=null和&depth<2)
{
ObjectToString(fld.GetValue(obj),sb,2);
}
其他的
{
sb.AppendLine(string.Format(“{0}字段名:{1};值:[{2}];类型:{3}”,“----->”,fld.Name,fld.GetValue(obj)?.ToString(),fld.FieldType?.FullName));
}
}
}
捕获(例外情况除外)
{
sb.AppendLine(“---->ObjectToString:depth(“+depth+”)+ex.Message中的异常);
}
使某人返回字符串();
}
使用反射访问成员属性的一个问题是速度太慢。
有一个很小的库,它使用一些动态生成的访问器代码,可以很快地完成这项工作。要使用它迭代所有公共字段和属性,您需要像下面这样运行简单的循环:
var ta = TypeAccessor.Create(typeof(MyClass));
foreach (var prop in ta.GetMembers())
{
Console.WriteLine(prop.Name);
}
var instance = new MyClass();
ta[instance, prop.Name] = "myvalue";
当您需要设置任何对象实例的字段或属性值时,可以这样做:
var ta = TypeAccessor.Create(typeof(MyClass));
foreach (var prop in ta.GetMembers())
{
Console.WriteLine(prop.Name);
}
var instance = new MyClass();
ta[instance, prop.Name] = "myvalue";
不,我只会从字段/属性获取(读取)信息!如果可以,我会试试