Создание динамического объекта LINQ без отражения (Activator.CreateInstance) и вызова метода - PullRequest
0 голосов
/ 26 ноября 2011

Я пишу конвейерную логику. Идея состоит в том, чтобы создавать экземпляры объекта «на лету» и выполнять методы Run в каждом случае. Я могу сделать старый способ с отражениями Activator.CreateInstance довольно легко, но производительность в этом случае важна.

Я посмотрел много примеров кода и учебных пособий, я думаю, что я правильно понял лямбда-выражение. Я могу понять только часть вызова. Заранее спасибо.

namespace Pipelines
{
using System;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;

public interface IProcessor
{
    string Name { get; set; }
}

public interface IAspNetMembershipId : IProcessor
{
    Guid? Id { get; set; }
}

public class ProcessorOne
{
    public void Run(IProcessor args)
    {
        /* Do Something */
    }
}

public class ProcessorTwo
{
    public void Run(IAspNetMembershipId args)
    {
        /* Do Something */
    }
}

public class Program
{
    static void Main(string[] args)
    {
        var arguments = new AspNetMembershipId() { Name = "jim" };

        /* Pipeline1 Begin */
        Type type = typeof(ProcessorOne);
        NewExpression newExp = Expression.New(type);

        var p1 = Expression.Parameter(newExp.Type, "ProcessorOne");
        var p2 = Expression.Parameter(typeof(IProcessor), "args");

        MethodInfo methodInfo = (from method in newExp.Type.GetMethods() where method.Name.StartsWith("Run") select method).First();
        var invokeExpression = Expression.Call(p1, methodInfo, p2);

        Delegate func = Expression.Lambda(invokeExpression, p1, p2).Compile();

        /* Throws an exception. This not correct! */
        func.DynamicInvoke(newExp, arguments);
        /* or */
        func.DynamicInvoke(arguments);

        /* Pipeline2 Begin */
    }
}

}

1 Ответ

0 голосов
/ 26 ноября 2011

Это должно работать:

var arguments = new AspNetMembershipId() { Name = "jim" };

/* Pipeline1 Begin */
Type type = typeof(ProcessorOne);

NewExpression newExp = Expression.New(type);

var p2 = Expression.Parameter(typeof(IProcessor), "args");

MethodInfo methodInfo = (from method in newExp.Type.GetMethods()
                            where method.Name.StartsWith("Run")
                            select method).First();

var invokeExpression = Expression.Call(newExp, methodInfo, p2);
Delegate func = Expression.Lambda(invokeExpression, p2).Compile();

/* Doesn't throw exception any more */
func.DynamicInvoke(arguments);

Обратите внимание, что я указал newExp непосредственно для invokeExpression и оставил arguments в качестве единственного параметра.

...