我正在使用非常相似的循环来迭代任何传递对象的所有公共字段和属性。我确定字段/属性是否用特定的自定义属性装饰;如果是这样,则对字段或属性的值执行操作。两个循环是必要的,因为获取字段值的方法与获取属性值的方法不同。
// Iterate all public fields using reflection
foreach (FieldInfo fi in obj.GetType().GetFields())
{
// Determine if decorated with MyAttribute.
var attribs = fi.GetCustomAttributes(typeof(MyAttribute), true);
if (attribs.Length == 1)
{
// Get value of field.
object value = fi.GetValue(obj);
DoAction(value);
}
}
// Iterate all public properties using reflection
foreach (PropertyInfo pi in obj.GetType().GetProperties())
{
// Determine if decorated with MyAttribute.
var attribs = pi.GetCustomAttributes(typeof(MyAttribute), true);
if (attribs.Length == 1)
{
// Get value of property.
object value = pi.GetValue(obj, null);
DoAction(value);
}
}
我想将循环放在一个单一的通用方法中,以便我可以更简单地编写:
DoEachMember(obj.GetType().GetFields());
DoEachMember(obj.GetType().GetProperties());
这需要DoEachMember()
接受MemberInfo
类型(它是 和 的父类型FieldInfo
)PropertyInfo
。问题是类中没有GetValue
方法MemberInfo
。两者都FieldInfo
使用PropertyInfo
不同的方法来获取字段/属性值:
public void DoEachMember(MemberInfo mi, object obj)
{
foreach (MemberInfo mi in obj.GetType().GetProperties())
{
object value mi.GetValue(obj); // NO SUCH METHOD!
}
}
因此,我声明了一个在循环中使用的委托,它接受 aMemberInfo
并将该成员的值作为对象返回:
// Delegate to get value from field or property.
delegate object GetValue(MemberInfo mi, object obj);
问题
如何检测members[]
数组中对象的类型,以便定义循环内使用的委托?目前,我正在使用数组的第一个元素members[0]
. 这是一个好的设计吗?
public void DoEachMember(MemberInfo[] members, object obj)
{
// Protect against empty array.
if (members.Length == 0) return;
GetValue getValue; // define delegate
// First element is FieldInfo
if (members[0] as FieldInfo != null)
getValue = (mi, obj) => ((FieldInfo)mi).GetValue(obj);
// First element is PropertyInfo
else if (members[0] as PropertyInfo != null)
getValue = (mi, obj) => ((PropertyInfo)mi).GetValue(obj, null);
// Anything else is unacceptable
else
throw new ArgumentException("Must be field or property.");
foreach (MemberInfo mi in members)
{
// Determine if decorated with MyAttribute.
var attribs = mi.GetCustomAttributes(typeof(MyAttribute), true);
if (attribs.Length == 1)
{
object value = getValue(mi, obj);
DoStuff(value);
}
}
}
或者,我可以在每次迭代时检测到类型,但应该没有理由个别数组成员会有所不同:
foreach (MemberInfo mi in members)
{
// ...
object value;
if ((var fi = mi as FieldInfo) != null)
value = fi.GetValue(obj);
else if ((var pi = mi as PropertyInfo) != null)
value = pi.GetValue(obj, null);
else
throw new ArgumentException("Must be field or property.");
DoStuff(value);
}