Bug 17534 - System.Reflection.PropertyInfo.GetValue(foo, new object[0]) doesn't work with FullAOT
Summary: System.Reflection.PropertyInfo.GetValue(foo, new object[0]) doesn't work with...
Status: RESOLVED INVALID
Alias: None
Product: Runtime
Classification: Mono
Component: Reflection ()
Version: unspecified
Hardware: PC Linux
: --- normal
Target Milestone: ---
Assignee: Bugzilla
URL:
Depends on:
Blocks:
 
Reported: 2014-01-31 06:23 UTC by Andres G. Aragoneses
Modified: 2014-01-31 07:13 UTC (History)
2 users (show)

Tags:
Is this bug a regression?: ---
Last known good build:

Notice (2018-05-24): bugzilla.xamarin.com is now in read-only mode.

Please join us on Visual Studio Developer Community and in the Xamarin and Mono organizations on GitHub to continue tracking issues. Bugzilla will remain available for reference in read-only mode. We will continue to work on open Bugzilla bugs, copy them to the new locations as needed for follow-up, and add the new items under Related Links.

Our sincere thanks to everyone who has contributed on this bug tracker over the years. Thanks also for your understanding as we make these adjustments and improvements for the future.


Please create a new report on GitHub or Developer Community with your current version information, steps to reproduce, and relevant error messages or log files if you are hitting an issue that looks similar to this resolved bug and you do not yet see a matching new report.

Related Links:
Status:
RESOLVED INVALID

Description Andres G. Aragoneses 2014-01-31 06:23:05 UTC
In http://docs.xamarin.com/guides/ios/advanced_topics/limitations/ it is said that System.Reflection (not S.R.E.) works fine with FullAOT.

However, this testcase doesn't:

using System;
using System.Collections.Generic;
using System.Linq.Expressions;
using System.Reflection;


namespace Test
{

	public class Row
    {
        public Guid Id { get; set; }
        public int Position { get; set; }
        public string Name { get; set; }
    }
	
    public class ADynamicReflectionHelper
    {
        public static PropertyInfo GetProperty(LambdaExpression expression)
        {
            var memberExpression = _GetMemberExpression(expression);
            var propertyInfo = memberExpression.Member as PropertyInfo;
            if (propertyInfo == null)
            {
                var message = string.Format("Could not find a property for expression {0}. Check that your are using a property and not a field", expression);
                throw new Exception(message);
            }

            return propertyInfo;
        }
        private static MemberExpression _GetMemberExpression(LambdaExpression expression)
        {
            MemberExpression memberExpression = null;

            if (expression.Body.NodeType == ExpressionType.Convert || expression.Body.NodeType == ExpressionType.TypeAs)
            {
                var body = (UnaryExpression) expression.Body;
                memberExpression = body.Operand as MemberExpression;
            }

            else if (expression.Body.NodeType == ExpressionType.MemberAccess)
            {
                memberExpression = expression.Body as MemberExpression;
            }

            return memberExpression;
        }
	}
	internal class SomeMapper <TRow, TProperty> {
		
		static Func<TRow, TProperty> callback;
		internal SomeMapper(Expression<Func<TRow, TProperty>> property) {
			PropertyInfo mPropertyInfo = ADynamicReflectionHelper.GetProperty (property);
			// callback = property.Compile (); <- illegal because uses CreateDelegate which uses SRE
			callback = (r) =>  (TProperty) mPropertyInfo.GetValue(r, new object[0]);
		}
		internal TProperty Resolve(TRow row) {
			return callback (row);
		}
	}

	class MainClass
	{
		public static void Main (string[] args)
		{
			var someMapper = new SomeMapper<Row, string>( x => x.Name );
			var row = new Row {
				Name = "foobar"
			};
			Console.WriteLine (">>>>>>>>>>" + someMapper.Resolve(row));
		}
	}
}


It throws the following:

[ERROR] FATAL UNHANDLED EXCEPTION: System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.ExecutionEngineException: Attempting to JIT compile method '(wrapper delegate-invoke) <Module>:invoke_string__this___GridBindingDemoViewModelRow (Test.GridBindingDemoViewModelRow)' while running with --aot-only. See http://docs.xamarin.com/ios/about/limitations for more information.

  at System.Reflection.MonoProperty.GetterAdapterFrame[GridBindingDemoViewModelRow,String] (System.Reflection.Getter`2 getter, System.Object obj) [0x00000] in <filename unknown>:0 
  at System.Reflection.MonoProperty.GetValue (System.Object obj, System.Object[] index) [0x00000] in <filename unknown>:0 
  --- End of inner exception stack trace ---
  at System.Reflection.MonoProperty.GetValue (System.Object obj, System.Object[] index) [0x00000] in <filename unknown>:0 
  at Test.SomeClass`2+<SomeClass>c__AnonStorey0[Test.GridBindingDemoViewModelRow,System.String].<>m__0 (Test.GridBindingDemoViewModelRow r) [0x00000] in <filename unknown>:0 
  at Test.SomeClass`2[Test.GridBindingDemoViewModelRow,System.String].Resolve (Test.GridBindingDemoViewModelRow row) [0x00000] in <filename unknown>:0 
  at Test.MainClass.Main (System.String[] args) [0x00000] in <filename unknown>:0
Comment 1 Andres G. Aragoneses 2014-01-31 06:35:05 UTC
Actually the testcase can be much more simple:

	public class Row
	{
		public Guid Id { get; set; }
		public int Position { get; set; }
		public string Name { get; set; }
	}
	

	class MainClass
	{
		public static void Main (string[] args)
		{
			var row = new Row {
				Name = "foobar"
			};
			var prop = row.GetType ().GetProperty ("Name");
			var val = prop.GetValue (row, new object[0]);
			Console.WriteLine ("!!!!!!!!!!" + val);
		}
	}
Comment 2 Andres G. Aragoneses 2014-01-31 07:13:55 UTC
Figured out I wasn't using class libraries compiled with FULL_AOT_RUNTIME.