我希望能够按名称访问属性或类的成员。如果它是一个属性我很好:
PropertyInfo prop = object.GetType().GetProperty(propertyName);
object propValue = prop.GetValue(object, null);
如果是会员/领域,事情似乎有点棘手。在研究GetMember
并尝试了一堆不同的东西之后,我无法弄清楚如何以GetProperty
返回的方式获取对象的引用,如果它是属性的话
另一个问题是,这是实现这一目标的正确方法吗?在阅读反思时,它似乎有很多开销。这只是与不使用反射相比,还是足够重要,我应该三思而后行,开发一些会做很多事情的东西,以及我有什么替代品,如果有的话,可以获得对一个成员的引用只按姓名分类?
感谢您的任何见解。如果它有任何区别,我的目标是能够序列化任意命名属性或类的成员。
答案 0 :(得分:4)
如果您想要检索字段,可以使用GetField代替GetProperty
。
FieldInfo field = object.GetType().GetField(fieldName);
object fieldValue = field.GetValue(Context.Parent);
还是足够重要,我应该三思而后行,开发一些会做很多事情的东西,以及我有什么选择,如果有的话,只能通过名字获得对一个类成员的引用?
这绝对是昂贵的,但我会对其进行分析,以确定您是否会遇到性能问题。
另一个主要选项是自己构建某种形式的字典,映射"名称"价值观。这可以是映射到值的直接字典,也可以是映射到检索值的委托的字典。这样做的好处在于,您可以使它以相同的方式用于属性或字段,但每个类都需要创建映射。 (但是,这可以通过施工时的反射来完成。)
如果它有任何区别,我的目标是能够序列化任意命名属性或类的成员。
我建议在推出自己的版本之前检查内置的Serialization Support ...
答案 1 :(得分:0)
如果你正在使用C#4.0(与.NET Framework 4.0和Visual Studio 2010一起发布),那么新的dynamic
关键字将简化代码中的内容:
dynamic myValue = anyObject;
string name = myValue.myField; // Resolved at runtime, not compile-time
bool result = myValue.myBooleanMethod(1, 2, 3); // Ditto
等。我的理解是,与使用反射和测试存在兼容的PropertyInfo
/ MethodInfo
/等相比,这或多或少是相同的。然后调用它们,因此性能仍然是一个问题,但它肯定更具可读性。
答案 2 :(得分:0)
我想出了什么用于缓存,欢迎评论。
public static ConcurrentDictionary<Tuple<Type, string>,
Func<object, object[], object>> ReflectionCache
{
get
{
if (_ReflectionCache==null) {
_ReflectionCache = new ConcurrentDictionary<Tuple<Type, string>,
Func<object, object[], object>>();
}
return _ReflectionCache;
}
} private static ConcurrentDictionary<Tuple<Type, string>,
Func<object, object[], object>> _ReflectionCache = null;
public static object GetCachedProperty(object obj, string name)
{
Func<object,object[],object> del;
if (!ReflectionCache.TryGetValue(Tuple.Create<Type,string>(obj.GetType(),
name), out del)) {
MemberInfo memberInfo =
(MemberInfo)obj.GetType().GetMember(name).GetValue(0);
PropertyInfo prop = null;
FieldInfo fld = null;
switch(memberInfo.MemberType) {
case MemberTypes.Field:
fld = obj.GetType().GetField(name);
break;
case MemberTypes.Property:
prop = obj.GetType().GetProperty(name);
break;
}
if (prop == null && fld == null)
{
throw new Exception("No property or field named '" + name
+ "' could be found in the context parent.");
}
if (prop!=null) {
prop= obj.GetType().GetProperty(name);
del = prop.GetValue;
} else {
fld = obj.GetType().GetField(name);
del = delegate(object cls,object[] index) {
return fld.GetValue(cls);
};
}
ReflectionCache[Tuple.Create<Type,string>(obj.GetType(),name)]=del;
}
return(del(obj,null));
}