如果在某处覆盖,我道歉。我在发帖前做过研究!
好的,所以问题......我正在使用GetType()。GetProperties,但它没有返回简单的实例字段,它们没有get / set ...所以我使用.GetFields,找到它们,但是我想得到一个简单的单个对象来获取/设置一个值而不在字段和属性之间翻转......这可能吗?
我当前的代码适用于PropertyInfo,它工作得很好,但这不适用于我猜的字段吗?
[编辑] 这是我提出的解决方案,效果很好。谢谢大家....
// some logic borrowed from James Newton-King, http://www.newtonsoft.com
public static void SetValue(this MemberInfo member, object property, object value)
{
if (member.MemberType == MemberTypes.Property)
((PropertyInfo)member).SetValue(property, value, null);
else if (member.MemberType == MemberTypes.Field)
((FieldInfo)member).SetValue(property, value);
else
throw new Exception("Property must be of type FieldInfo or PropertyInfo");
}
public static object GetValue(this MemberInfo member, object property)
{
if (member.MemberType == MemberTypes.Property)
return ((PropertyInfo)member).GetValue(property, null);
else if (member.MemberType == MemberTypes.Field)
return ((FieldInfo)member).GetValue(property);
else
throw new Exception("Property must be of type FieldInfo or PropertyInfo");
}
public static Type GetType(this MemberInfo member)
{
switch (member.MemberType)
{
case MemberTypes.Field:
return ((FieldInfo)member).FieldType;
case MemberTypes.Property:
return ((PropertyInfo)member).PropertyType;
case MemberTypes.Event:
return ((EventInfo)member).EventHandlerType;
default:
throw new ArgumentException("MemberInfo must be if type FieldInfo, PropertyInfo or EventInfo", "member");
}
}
答案 0 :(得分:29)
怎么样:
const BindingFlags bindingFlags = BindingFlags.Public | BindingFlags.Instance;
MemberInfo[] members = type.GetFields(bindingFlags).Cast<MemberInfo>()
.Concat(type.GetProperties(bindingFlags)).ToArray();
或者,像FastMember这样的库可以很好地使用字段或属性,无论成员类型如何,get / set都相同。
答案 1 :(得分:11)
GetProperties()和GetFields()的返回类型是不同的,正如您似乎注意到的那样。您必须使用GetValue()和SetValue()定义接口,并使用扩展ParameterInfo和FieldInfo来实现此接口。这可能是一个包装器:
interface IGetSettable
{
public void SetValue(
Object obj,
Object value,
Object[] index);
public Object GetValue(
Object obj,
Object[] index);
}
public class ParameterInfoGS : IGetSettable
{
protected ParameterInfo pi;
public ParameterInfoExtra(ParameterInfo _pi)
{
pi = _pi;
}
public void SetValue(
Object obj,
Object value,
Object[] index) {pi.SetValue(obj, value, index);}
public Object GetValue(
Object obj,
Object[] index) {return pi.GetValue(obj, index);}
}
public class FieldInfoGS : IGetSettable
{
protected FieldInfo pi;
public FieldInfoExtra(FieldInfo _pi)
{
pi = _pi;
}
public void SetValue(
Object obj,
Object value,
Object[] index) {pi.SetValue(obj, value, index);}
public Object GetValue(
Object obj,
Object[] index) {return pi.GetValue(obj, index);}
}
public static class AssemblyExtension
{
public static IGetSettable[] GetParametersAndFields(this Type t)
{
List<IGetSettable> retList = new List<IGetSettable>();
foreach(ParameterInfo pi in t.GetParameters())
retList.Add(new ParameterInfoExtra(pi));
foreach(FieldInfo fi in t.GetFields())
retList.Add(new FieldInfoExtra(fi));
return retList.ToArray();
}
}
这将允许您GetType().GetParametersAndFields()
(即使用标准反射类型)。
答案 2 :(得分:6)
有点晚了,但我想出了以下...... 1循环,就像魅力一样; - )
MemberInfo[] memberInfos = dotNetType.GetMembers();
ModelPropertySpec modelPropertySpec;
foreach (MemberInfo memberInfo in memberInfos)
{
Type itemType = null;
String memberName = memberInfo.Name;
switch (memberInfo.MemberType)
{
case MemberTypes.Property:
itemType = dotNetType.GetProperty(memberName).PropertyType;
break;
case MemberTypes.Field:
itemType = dotNetType.GetField(memberName).FieldType;
break;
}
if (itemType != null)
{
modelPropertySpec = ParsePropertyType(memberName, itemType);
modelSpec.Properties.Add(modelPropertySpec.Name, modelPropertySpec);
}
}
答案 3 :(得分:5)
要获取属性或字段,您可以说:
bindingAttr
其中var bindingAttr=
BindingFlags.NonPublic|
BindingFlags.Public|
BindingFlags.Instance;
可能是
BindingFlags.NonPublic
如果您不想获得非公开会员,请移除InvokeMember
。顺便说一句,查询不是一个调用,而是一个语句。
要获取属性或字段的值而不自行投射,请使用static object GetValue<T>(
T x, object target) where T:MemberInfo {
var invokeAttr=(
x is FieldInfo
?BindingFlags.GetField
:x is PropertyInfo
?BindingFlags.GetProperty
:BindingFlags.Default)|
BindingFlags.NonPublic|
BindingFlags.Public|
BindingFlags.Instance;
return target.GetType().InvokeMember(
x.Name, invokeAttr, default(Binder), target, null);
}
获取技巧:
static void SetValue<T>(
T x, object target, object value) where T:MemberInfo {
var args=new object[] { value };
var invokeAttr=(
x is FieldInfo
?BindingFlags.SetField
:x is PropertyInfo
?BindingFlags.SetProperty
:BindingFlags.Default)|
BindingFlags.NonPublic|
BindingFlags.Public|
BindingFlags.Instance;
target.GetType().InvokeMember(
x.Name, invokeAttr, default(Binder), target, args);
}
同样,要设置值:
MemberInfo
如果您传递PropertyInfo
以外的FieldInfo
或BindingFlags.Default
作为第一个参数,则会抛出,因为@root ~/a $ zipinfo -1 data.zip
a.txt
b.txt
test/
test/c.txt
root@ ~/a $ find .
.
./test
./test/c.txt
./b.txt
./data.zip
./a.txt
没有指定您要执行的操作做。
答案 4 :(得分:3)
使用DLR(如果您在编译时知道成员名称,那么就够了):
((dynamic)obj).MyFieldOrPropertyName = myValue;
如果您只知道运行时的成员名称,我建议使用FastMember,正如Marc Gravell建议的那样。