how to get both fields and properties in single call via reflection?

后端 未结 5 893
时光说笑
时光说笑 2020-12-03 05:05

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

相关标签:
5条回答
  • 2020-12-03 05:25

    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.

    0 讨论(0)
  • 2020-12-03 05:26

    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);
                }
            }
    
    0 讨论(0)
  • 2020-12-03 05:32

    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.

    0 讨论(0)
  • 2020-12-03 05:35

    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).

    0 讨论(0)
  • 2020-12-03 05:35

    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.

    0 讨论(0)
提交回复
热议问题