预编译的 lambda 表达式以创建具有带参数的构造函数的类

我目前正在使用Activator.CreateInstance创建其类型作为泛型参数传入的类的实例。问题是,这非常慢。我在某处读到我可以使用预编译的 lambda 表达式做同样的事情,但是,由于需要将参数传递给正在创建的类的实例,因此在我的情况下我无法实现这一点。


目前我正在做以下事情


public class Class1

{

    private int TestVariable;


    public Class1(int testVariable)

    {

        TestVariable = testVariable;

    }


    public void TestMethod()

    {

        Console.WriteLine($"Test Variable was {TestVariable}");

    }

}


public object Test<T>(params object[] parameters)

{

    var instance = (T) Activator.CreateInstance(typeof(T), BindingFlags.Instance, null, new object[] {9999}, null);


    var testMethod = typeof(T).GetMethod("TestMethod", BindingFlags.Instance);


    return testMethod.Invoke(instance, parameters)

}

如何使用预编译的 lambda 表达式完成类似的操作?


DIEA
浏览 81回答 1
1回答

蛊毒传说

实际上,如果您只需要创建一个对象,使用Expression.Compile会更慢。但是,如果您缓存创建者函数,从长远来看它会更快,因为 lambda 性能会很好。这是代码:static Func<TArg, T> CreateCreator<TArg, T>(){&nbsp; &nbsp; var constructor = typeof(T).GetConstructor(new Type[] { typeof(TArg) });&nbsp; &nbsp; var parameter = Expression.Parameter(typeof(TArg), "p");&nbsp; &nbsp; var creatorExpression = Expression.Lambda<Func<TArg, T>>(&nbsp; &nbsp; &nbsp; &nbsp; Expression.New(constructor, new Expression[] { parameter }), parameter);&nbsp; &nbsp; return creatorExpression.Compile();}Func<TArg, T> creator = CreateCreator<TArg, T>();有了这个,你可以creator(arg)用来创建T.三种方式的小基准:class Program{&nbsp; &nbsp; static void Main(string[] args)&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; // warm up&nbsp; &nbsp; &nbsp; &nbsp; Test1<Class1>(0);&nbsp; &nbsp; &nbsp; &nbsp; Test2<int, Class1>(0);&nbsp; &nbsp; &nbsp; &nbsp; const int numiter = 10000;&nbsp; &nbsp; &nbsp; &nbsp; var sw1 = Stopwatch.StartNew();&nbsp; &nbsp; &nbsp; &nbsp; for (int i = 0; i < numiter; i++)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Test1<Class1>(i);&nbsp; &nbsp; &nbsp; &nbsp; sw1.Stop();&nbsp; &nbsp; &nbsp; &nbsp; Console.WriteLine($"With Activator.CreateInstance: " +&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $"{(double)sw1.ElapsedTicks / numiter} ticks per object");&nbsp; &nbsp; &nbsp; &nbsp; var sw2 = Stopwatch.StartNew();&nbsp; &nbsp; &nbsp; &nbsp; for (int i = 0; i < numiter; i++)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Test2<int, Class1>(i);&nbsp; &nbsp; &nbsp; &nbsp; sw2.Stop();&nbsp; &nbsp; &nbsp; &nbsp; Console.WriteLine($"With Expression.Compile: " +&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $"{(double)sw2.ElapsedTicks / numiter} ticks per object");&nbsp; &nbsp; &nbsp; &nbsp; var sw3 = Stopwatch.StartNew();&nbsp; &nbsp; &nbsp; &nbsp; var creator = CreateCreator<int, Class1>();&nbsp; &nbsp; &nbsp; &nbsp; for (int i = 0; i < numiter; i++)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; creator(i);&nbsp; &nbsp; &nbsp; &nbsp; sw3.Stop();&nbsp; &nbsp; &nbsp; &nbsp; Console.WriteLine($"With cached Expression.Compile: " +&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $"{(double)sw3.ElapsedTicks / numiter} ticks per object");&nbsp; &nbsp; }&nbsp; &nbsp; static public object Test1<T>(params object[] parameters)&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; var instance = (T)Activator.CreateInstance(&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; typeof(T), BindingFlags.Instance | BindingFlags.Public, null, parameters, null);&nbsp; &nbsp; &nbsp; &nbsp; return instance;&nbsp; &nbsp; }&nbsp; &nbsp; static Func<TArg, T> CreateCreator<TArg, T>()&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; var constructor = typeof(T).GetConstructor(new Type[] { typeof(TArg) });&nbsp; &nbsp; &nbsp; &nbsp; var parameter = Expression.Parameter(typeof(TArg), "p");&nbsp; &nbsp; &nbsp; &nbsp; var creatorExpression = Expression.Lambda<Func<TArg, T>>(&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Expression.New(constructor, new Expression[] { parameter }), parameter);&nbsp; &nbsp; &nbsp; &nbsp; return creatorExpression.Compile();&nbsp; &nbsp; }&nbsp; &nbsp; static public object Test2<TArg, T>(TArg arg)&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; var creator = CreateCreator<TArg, T>();&nbsp; &nbsp; &nbsp; &nbsp; return creator(arg);&nbsp; &nbsp; }}在我的机器上产生以下结果(发布模式/在 Visual Studio 之外):With Activator.CreateInstance: 3.0739 ticks per objectWith Expression.Compile: 494.0388 ticks per objectWith cached Expression.Compile: 0.1097 ticks per object
打开App,查看更多内容
随时随地看视频慕课网APP