Mik*_*ilt 8 c# reflection lambda activator
我和朋友正在测试使用编译表达式来创建对象,而不是Activator.CreateInstance<T>
遇到一些有趣的结果.我们发现当我们在每台机器上运行相同的代码时,我们看到完全相反的结果.他得到了预期的结果,在编译表达式中表现明显更好,而我惊讶地看到Activator.CreateInstance<T>
表现为2x.
两台计算机都运行在.NET 4.0中编译
计算机1安装了.NET 4.5.电脑2没有.
计算机1超过100000个对象:
45ms - Type<Test>.New()
19ms - System.Activator.CreateInstance<Test>();
Run Code Online (Sandbox Code Playgroud)
计算机2超过100000个对象:
13ms - Type<Test>.New()
86ms - System.Activator.CreateInstance<Test>();
Run Code Online (Sandbox Code Playgroud)
以下是代码:
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Linq.Expressions;
namespace NewNew
{
class Program
{
static void Main(string[] args)
{
Stopwatch benchmark = Stopwatch.StartNew();
for (int i = 0; i < 100000; i++)
{
var result = Type<Test>.New();
}
benchmark.Stop();
Console.WriteLine(benchmark.ElapsedMilliseconds + " Type<Test>.New()");
benchmark = Stopwatch.StartNew();
for (int i = 0; i < 100000; i++)
{
System.Activator.CreateInstance<Test>();
}
benchmark.Stop();
Console.WriteLine(benchmark.ElapsedMilliseconds + " System.Activator.CreateInstance<Test>();");
Console.Read();
}
static T Create<T>(params object[] args)
{
var types = args.Select(p => p.GetType()).ToArray();
var ctor = typeof(T).GetConstructor(types);
var exnew = Expression.New(ctor);
var lambda = Expression.Lambda<T>(exnew);
var compiled = lambda.Compile();
return compiled;
}
}
public delegate object ObjectActivator(params object[] args);
public static class TypeExtensions
{
public static object New(this Type input, params object[] args)
{
if (TypeCache.Cache.ContainsKey(input))
return TypeCache.Cache[input](args);
var types = args.Select(p => p.GetType());
var constructor = input.GetConstructor(types.ToArray());
var paraminfo = constructor.GetParameters();
var paramex = Expression.Parameter(typeof(object[]), "args");
var argex = new Expression[paraminfo.Length];
for (int i = 0; i < paraminfo.Length; i++)
{
var index = Expression.Constant(i);
var paramType = paraminfo[i].ParameterType;
var accessor = Expression.ArrayIndex(paramex, index);
var cast = Expression.Convert(accessor, paramType);
argex[i] = cast;
}
var newex = Expression.New(constructor, argex);
var lambda = Expression.Lambda(typeof(ObjectActivator), newex, paramex);
var result = (ObjectActivator)lambda.Compile();
TypeCache.Cache.Add(input, result);
return result(args);
}
}
public class TypeCache
{
internal static IDictionary<Type, ObjectActivator> Cache;
static TypeCache()
{
Cache = new Dictionary<Type, ObjectActivator>();
}
}
public class Type<T>
{
public static T New(params object[] args)
{
return (T)typeof(T).New(args);
}
}
public class Test
{
public Test()
{
}
public Test(string name)
{
Name = name;
}
public string Name { get; set; }
}
}
Run Code Online (Sandbox Code Playgroud)
小智 8
至少有两个原因:
Type<Test>.New()
或System.Activator.CreateInstance<Test>()
第一次的开销相对较大.因此,我改变了100000到10000000.有了这两个变化,这两种方法大约需要相同的时间.在我的系统上,对于这两种方法,我在1100到1200之间,有时一个更高,有时另一个.
请注意,Activator.CreateInstance<T>()
只能调用默认构造函数,而您New()
接受许多参数.如果你的New()
功能不那么强大,并且总是使用默认的构造函数,那么它比Activator.CreateInstance<T>()
我的系统稍快一些.
另请注意,如果应使用两个相同类型的不同构造函数,则使用参数构造函数的处理实际上不起作用,具体取决于传递的参数.您可以选择一个构造函数用于整个程序的其余部分.
归档时间: |
|
查看次数: |
4404 次 |
最近记录: |