【发布时间】:2024-04-25 20:10:01
【问题描述】:
我需要调用如下所示的方法:
public bool DoSomething<TEntity>(Expression<Func<TEntity, bool>> expression, Action<TEntity> action) where TEntity : class
但是 TEntity 仅在运行时才知道。
我知道如何调用这样的方法:
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>);
如您所见,我不知道将什么传递给函数。这就是与This Question 的不同之处,后者调用了无参数的方法。
有什么办法可以做到吗?
编辑:完整示例
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--)
{
}
}
}
【问题讨论】:
-
这个问题不清楚。你到底想用
expression和TEntity做什么? -
@Liam 我编辑了这个问题。希望它现在清楚了。我不知何故需要构建一个只有在运行时才知道的确切类型的表达式和动作。
-
WHAT GOES HERE,你的参数。您如何将参数传递到您调用它的任何地方?这还不清楚。请为您的问题创建一个Minimal, Complete, and Verifiable example -
@Liam 我附上了完整的例子。
-
好吧,这是一个非常多的代码,只是为了替换 where 子句。反射也将是低效的。为什么你需要对看似简单的代码块进行这种级别的重用。我认为你做这个比它需要的要复杂得多,实际上是零收益。
标签: c# generics reflection anonymous-methods