C# Вызов метода generi c с типом в виде строки с лямбда-аргументом - PullRequest
1 голос
/ 07 августа 2020

Допустим, у меня есть:

public class ConcreteJob
{
    public void ExecuteConcreteJob(string someParam) { }
}

Я привык выполнять его в планировщике Hangfire:

var client = new BackgroundJobClient();
client.Enqueue<ConcreteJob>(job => job.ExecuteConcreteJob("test_string_param"));

Теперь я хотел бы заменить конкретный тип ConcreteJob его строкой Представительство "ConcreteJob". Используйте отражение и сделайте что-то вроде этого (очень просто сказано):

client.Enqueue<"ConcreteJob">(job => job.ExecuteConcreteJob("test_string_param"));

Я теряюсь во всех отражениях ...

Параметр Lambda как отличается от других потоки при переполнении стека.

То, что у меня есть:

var jobType = Type.GetType("ConcreteJob");
MethodInfo methodInfo = typeof(BackgroundJobClient).GetMethod("Enqueue").MakeGenericMethod(jobType);
var funcDelegateType = typeof(Func<>).MakeGenericType(jobType);
dynamic lambda = Expression.Lambda(funcDelegateType,
        Expression.Call(
            Expression.Parameter(jobType, "job"),
            jobType.GetMethod("ExecuteCleanup"),
            Expression.Constant(UserPrincipalName))
    );
methodInfo.Invoke(client, new[] { (Action)(lambda) });

1 Ответ

1 голос
/ 10 августа 2020

Лямбда как параметр отличает его от других потоков при переполнении стека.

Метод ExecuteCleanup принимает делегат в качестве параметра, а не лямбда-выражение. Следовательно, вам необходимо скомпилировать ваше лямбда-выражение в делегат, прежде чем передавать его в качестве параметра.

Обратите внимание, что это не дешевая операция. Имеет смысл где-то кэшировать скомпилированные делегаты и повторно использовать их.

Поскольку ваше лямбда-выражение принимает параметр, вам необходимо объявить этот параметр и передать его в Expression.LambdaMethod.

MethodInfo methodInfo = typeof(BackgroundJobClient).GetMethod("Enqueue").MakeGenericMethod(jobType);
var funcDelegateType = typeof(Action<>).MakeGenericType(jobType);
ParameterExpression parameter = Expression.Parameter(jobType, "job");
LambdaExpression lambda = Expression.Lambda(funcDelegateType,
        Expression.Call(
            parameter,
            jobType.GetMethod("ExecuteCleanup"),
            Expression.Constant(UserPrincipalName)),
        parameter
    );
methodInfo.Invoke(client, new[] { lambda.Compile() });
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...