I need to call a method that looks like this:
public bool DoSomething<TEntity>(Expression<Func<TEntity, bool>> expression, Action<TEntity> action) where TEntity : class
However TEntity is only known at runtime.
I know how to Invoke the method like this:
Type classType = GetType();
MethodInfo mInfo = classType.GetMethod("DoSomething", BindingFlags.Public | BindingFlags.Instance);
MethodInfo genericMInfo = mInfo.MakeGenericMethod(GetMyType());
Object result = genericMInfo.Invoke(this, <WHAT GOES HERE>);
As you can see i don't know what to pass into the function. And thats the diffrence to This Question where a method without parameters is called.
Is there any way i can do this?
EDIT: Full Example
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
namespace Example
{
public class Program
{
static void Main(string[] args)
{
var example = new Example();
// Type know at compiletime:
example.DoSomething<MyClass>((obj) => obj.Number > 2, (obj) => obj.Number = 500);
// Type not know until runtime. Might be MyClass, MyOtherClass or MyNextClass
Type classType = example.GetType();
MethodInfo mInfo = classType.GetMethod("DoSomething", BindingFlags.Public | BindingFlags.Instance);
MethodInfo genericMInfo = mInfo.MakeGenericMethod(GetMyType());
var result = genericMInfo.Invoke(example, new object[] { /* Expression<Func<TEntity, bool>> and Action<TEntity> */ });
// My problem now is how to create this Expression and Action even if i know TEntity only at runtime
}
static Type GetMyType()
{
// Imagine some user-input or any other dark magic here. For the example i`ll just return a type
return typeof(MyOtherClass);
}
}
public class Example
{
public bool DoSomething<TEntity>(Expression<Func<TEntity, bool>> expression, Action<TEntity> action) where TEntity : MyClass
{
// Real code does something more useful, but its the same principle
var myList = new List<TEntity>(GetItems<TEntity>());
if (myList.Count > 0)
{
var entry = myList.AsQueryable().Where(expression).FirstOrDefault();
if (entry != null)
{
action(entry);
return true;
}
}
return false;
}
private IEnumerable<T> GetItems<T>()
{
// Real code does something diffrent
for (int i = 0; i < 5; i++)
{
yield return (T)Activator.CreateInstance(typeof(T), i);
}
}
}
public class MyClass
{
public MyClass(int number)
{
Number = number;
}
public int Number { get; set; }
}
public class MyOtherClass : MyClass
{
public MyOtherClass(int number)
: base(number++)
{
}
}
public class MyNextClass : MyClass
{
public MyNextClass(int number)
: base(number--)
{
}
}
}
Aucun commentaire:
Enregistrer un commentaire