I'm trying to creating a dynamic base mapping with fluent nhibernate.
What I'm doing is checking in by a BaseMap< T > : ClassMap< T > if for example: (typeof(ICategorizedEntity).IsAssignableFrom(typeof(T)))
If so, I wanna map a property named "Category" which belongs to ICategorizedEntity's interface, but the Map(Func) function only accepts T's properties, so I tried guessing a little with linq and came up with this:
Expression<Func<ICategorizedEntity, object>> exp = x => x.Category;
var parameter = Expression.Parameter(typeof (T));
var lmd = Expression.Lambda<Func<T, object>>(exp, parameter);
Map(lmd);
Which doesn't work, because deep inside the 'Map' function it checks the following:
MemberExpression memberExpression = (MemberExpression) null;
if (expression.NodeType == ExpressionType.Convert)
memberExpression = ((UnaryExpression) expression).Operand as MemberExpression;
else if (expression.NodeType == ExpressionType.MemberAccess)
memberExpression = expression as MemberExpression;
if (enforceCheck && memberExpression == null)
throw new ArgumentException("Not a member access", "expression");
And I get the "Not a member access\r\nParameter name: expression".
How can I create and cast a MemberExpression or anything similar which will work?
Func<DerivedFromT,object> represents a method that accepts a DerivedFromT parameter. Func<T,object> represents a method that accepts a T parameter. Through delegate variance introduced in C# 4, you can cast Func<T,object> to Func<DerivedFromT,object>, but not the other way round (as you’re requesting).
Think about what this means:
public class Person { }
public class Student : Person { }
public static class School
{
public static object Greet(Person person)
{
return null;
}
public static object Promote(Student student)
{
return null;
}
}
In this case, the Greet method matches the delegate Func<Person,object>, whilst the Promote method matches the delegate Func<Student,object>.
Func<Person, object> greetPerson = School.Greet;
Func<Student, object> promoteStudent = School.Promote;
We can cast Greet to Func<Student,object>; if we can greet a Person, then we can also greet a Student (who is guaranteed to be a specialized form of Person).
Func<Student, object> greetStudent = greetPerson;
However, we cannot cast Promote to Func<Person,object>; although we can promote a Student, we cannot promote any Person in general, unless he/she happens to be a Student.
Func<Person, object> promotePerson = promoteStudent; // Will not compile.
If we know that our Person is a student, we can indicate this by casting it:
Func<Person, object> promotePerson =
personWhoIsActuallyStudent => promoteStudent((Student)personWhoIsActuallyStudent);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With