I need the realType
functionality of the following code as the Class in the Expression
I am inspecting is a SubClass and memberExpression.Member
returns information from the Base class.
This is for our blazor component library for the purposes of getting attributes on our Form models
I have read several articles and understand the problem and the solution however this raises a new issue in the context of net7 trimming.
Code taken from
https://stackoverflow.com/questions/9466582/how-to-get-the-child-declaring-type-from-an-expression
/// <summary>
/// Extracts the PropertyInfo for the property being accessed in the given expression.
/// </summary>
/// <remarks>
/// If possible, the actual owning type of the property is used, rather than the declaring class (so if "x" in "() => x.Foo" is a subclass overriding "Foo", then x's PropertyInfo for "Foo" is returned rather than the declaring base class's PropertyInfo for "Foo").
/// </remarks>
/// <typeparam name="T"></typeparam>
/// <param name="propertyExpression"></param>
/// <returns></returns>
internal static PropertyInfo ExtractPropertyInfo<T>(Expression<Func<T>> propertyExpression)
{
if (propertyExpression == null)
{
throw new ArgumentNullException("propertyExpression");
}
var memberExpression = propertyExpression.Body as MemberExpression;
if (memberExpression == null)
{
throw new ArgumentException(string.Format("Expression not a MemberExpresssion: {0}", propertyExpression), "propertyExpression");
}
var property = memberExpression.Member as PropertyInfo;
if (property == null)
{
throw new ArgumentException(string.Format("Expression not a Property: {0}", propertyExpression), "propertyExpression");
}
var getMethod = property.GetGetMethod(true);
if (getMethod.IsStatic)
{
throw new ArgumentException(string.Format("Expression cannot be static: {0}", propertyExpression), "propertyExpression");
}
Type realType = memberExpression.Expression.Type;
if(realType == null) throw new ArgumentException(string.Format("Expression has no DeclaringType: {0}", propertyExpression), "propertyExpression");
return realType.GetProperty(property.Name);
}
This code is perfect for my needs. The key to getting to the SubClass is this
Type realType = memberExpression.Expression.Type;
However the linker complains about this code in net7.
return realType.GetProperty(property.Name);
The compiler warning states that
(local variable) PropertyInfo property
'this' argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicProperties' in call to 'System.Type.GetProperty(String)'. The return value of method 'System.Linq.Expressions.Expression.Type.get' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to. \[MudBlazor\]csharp(IL2075)
Since GetProperty
is annotated with DynamicallyAccessedMemberTypes.PublicProperties
but Type
is not, the trimmer can't follow the full chain of annotations.
Can this code be made trim compatible? Will the trimmer know how to preserve the types (including child types) if I just ignore (pragma) this warning?
I tried to see how Type
is implemented in netcore but it is a lookup on an internal Dictionary
so I couldn't recreate the functionality.
I also tried looking to see if I could ascertain the SubClass Type in some other "trim friendly" way.