Oworo
Oworo

Reputation: 19

C# Get Method by reflection with Expression<Func<TEntity,object>> in Parameter

i am new to reflection and hope you can help me out. I find a lot questions similar to mine but does not get it transmitted on my Problem.

I have a method:

IEnumerable<TEntity> Get<TEntity>(Expression<Func<TEntity, object>> propertyNameExpression, object propertyValue) where TEntity : NT.Base.Framework.ODL.Entity;

I normally call this Method like this: PersistentService.Get<Agent>(a => a.ID, Guid.Empty);

But now i know it only at run time which class i have. So i have a

Type classType;

And need to know how to call this method with the classType. I have a temporary solution, where i take the method with a string but hardcoded strings in code are not so nice.

MethodInfo methodInfo = typeof(PersistenceService).GetMethod("Get", new Type[] { classType, typeof(string) });
var classMethod = methodInfo.MakeGenericMethod(classType);
string query = "SELECT * FROM " + classType.Name + " WHERE " + classType.Name + ".Id = '" + pg.GUID.ToString() + "'";
dynamic dEnumeration = classMethod.Invoke(PersistenceService, new object[] { query });
dynamic dEntity = Enumerable.FirstOrDefault(dEnumeration);

Edit: I tried the following but methodInfo is always NULL

ParameterExpression parameter = Expression.Parameter(typeof(Entity), "a");         
var delegateType = typeof(Func<,>).MakeGenericType(typeof(Entity), typeof(object));                        
var yourExpression = Expression.Lambda(delegateType, parameter, parameter);                        
MethodInfo methodInfo = typeof(PersistenceService).GetMethod("Get", new Type[] { yourExpression.GetType(), typeof(object) });

The Type of yourExpression.GetType() is:

{Name = "Expression`1" FullName = "System.Linq.Expressions.Expression`1[[System.Func`2[[NT.Base.Framework.ODL.Entity, NT.Base.Framework.ODL, Version=0.0.0.126, Culture=neutral, PublicKeyToken=null],[System.Object, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]"}    System.Type {System.RuntimeType}

So please help me, how to get and invoke this method.

Upvotes: 1

Views: 1700

Answers (1)

Oworo
Oworo

Reputation: 19

I got it by my own:

ParameterExpression parameter = Expression.Parameter(classType, "a");

//a.Id GUID
MemberExpression property = Expression.Property(parameter, "Id");
//a.ID as object
var newProp = Expression.TypeAs(property, typeof(object));
var delegateType = typeof(Func<,>).MakeGenericType(classType, typeof(object));
var yourExpression = Expression.Lambda(delegateType, newProp, parameter);

MethodInfo methodInfo = typeof(PersistenceService).GetMethods()
.Where(x => x.Name == "Get")
.Select(x => new { M = x, P = x.GetParameters() })
.Where(x => x.P.Length == 2
            && x.P[0].ParameterType.IsGenericType
            && x.P[0].ParameterType.GetGenericTypeDefinition() == typeof(Expression<>)                             
            && x.P[1].ParameterType == typeof(object))
.Select(x => new { x.M, A = x.P[0].ParameterType.GetGenericArguments() })
.Where(x => x.A[0].IsGenericType
            && x.A[0].GetGenericTypeDefinition() == typeof(Func<,>))
.Select(x => new { x.M, A = x.A[0].GetGenericArguments() })
.Where(x => x.A[0].IsGenericParameter
            && x.A[1] == typeof(object))
.Select(x => x.M)
.SingleOrDefault();

if(methodInfo != null)
{
    MethodInfo method = methodInfo.MakeGenericMethod(classType);
    dynamic dEnumeration = method.Invoke(PersistenceService, new object[] { yourExpression, pg.GUID });
    dynamic dEntity = Enumerable.FirstOrDefault(dEnumeration);
    ...

Upvotes: 1

Related Questions