I apologize if this is covered somewhere. I did research before posting!
okay, so question...I\'m using GetType( ).GetProperties, but it isn\'t returning simple inst
To get either properties or fields, you can say:
var q=
from it in type.GetMembers(bindingAttr)
where it is PropertyInfo||it is FieldInfo
select it;
where bindingAttr
could be
var bindingAttr=
BindingFlags.NonPublic|
BindingFlags.Public|
BindingFlags.Instance;
Remove BindingFlags.NonPublic
if you don't want to get non-public members. By the way, the query is not a single call but a single statement.
To get the value of either a property or a field without casting it by yourself, use InvokeMember
for the trick:
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);
}
Similarly, to set the value:
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);
}
It will throw if you pass a MemberInfo
other than PropertyInfo
or FieldInfo
as the first argument, because BindingFlags.Default
doesn't specify what you are going to do.
A bit late, but I came up with the following ... 1 loop, works like a charm ;-)
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);
}
}
How about:
const BindingFlags bindingFlags = BindingFlags.Public | BindingFlags.Instance;
MemberInfo[] members = type.GetFields(bindingFlags).Cast<MemberInfo>()
.Concat(type.GetProperties(bindingFlags)).ToArray();
Alternatively, libraries like FastMember will work happily with either fields or properties, with get/set identical regardless of the member-type.
The return types of GetProperties() and GetFields() are different, as you seem to have noticed. You would have to define an interface with the GetValue() and SetValue() and use extend ParameterInfo and FieldInfo to implement this interface. This would probably work as a wrapper:
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();
}
}
This will allow you to do GetType().GetParametersAndFields()
(i.e. use the standard reflection types).
Using DLR (simple enough, if you know the member name at compile time):
((dynamic)obj).MyFieldOrPropertyName = myValue;
If you only know the member name at run-time, I'd recommend FastMember, as Marc Gravell suggested.