Type.GetProperties returning nothing

2019-06-19 07:23发布

问题:

Consider the following code:

public class MyClass
{
    public MyClass(Type optionsClassType)
    {
      //A PropertyInfo[0] is returned here
      var test1 = optionsClassType.GetProperties();
      //Even using typeof
      var test2 = typeof(MyClassOptions).GetProperties();
     //Or BindingFlags
      var test3 = typeof(MyClassOptions)
          .GetProperties(BindingFlags.DeclaredOnly | BindingFlags.Public);
    }
}

public class MyClassOptions
{
    public int MyProperty { get; set; }
}

I'm unable to get PropertyInfo[] about MyClassOptions, Type.GetProperties always returns an empty array. First I thought that was a framework bug in Xamarin.iOS, but I tested the same code in another project targeting the same framework and it worked just fine.

Anyone knows possible causes for this?

EDIT

Thanks to @Fabian Bigler answer I got it. In my project, even with Linker set to a moderate behavior, instantiating MyClassOptions was not enough to keep the class definition at runtime. Only after actually using the instance(e.g. setting a property) the class is kept in my build.

Seems that linker replaces "unused" stuff with dummies. Since I'll use reflection a lot in this project I've just disabled the Linker and everything is working again.

回答1:

This code works perfectly fine for me:

namespace MyNameSpace
{
    public class MyClass
    {
        public MyClass(Type optionsClassType)
        {
            //A PropertyInfo[0] is returned here
            var test1 = optionsClassType.GetProperties();
            //Even using typeof
            var test2 = typeof(MyClassOptions).GetProperties();
            //Or BindingFlags
            var test3 = typeof(MyClassOptions).GetProperties
(BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.Instance);
        }
    }

    public class MyClassOptions
    {
        public int MyProperty { get; set; }
    }
}

Added BindingFlags.Instance in code. For further information, have a look at this post.


Then call this from outside:

var options = new MyClassOptions();
    options.MyProperty = 1234;
    var t = options.GetType();
    var c = new MyNameSpace.MyClass(t);

NOTE: Be careful with assembly linker

If you're building with linker enabled you may need to use the class somewhere, so it will not be ripped off at compile time. Sometimes, only instantiating the class in your code is not enough, the linker may detect that the instance is never used and will remove it anyway.