原來程序中的代碼:html
public static T GetInstance<T>() where T : new() { return new T(); }
須要擴展這個方法支持參數傳遞。惋惜泛型約束不支持指定構造函數參數,那隻好使用對象反射了。express
public class A { public A(string A) { } public string P1 { get; set; } } //反射建立對象A Activator.CreateInstance(t, "sss");
這樣的話對象建立速度一下會變得很慢吧。正好想到 ExpressionTree,使用Expression.New而且緩存Expression方式應該能夠提升些速度。正好找到了相關用法 http://geekswithblogs.net/mrsteve/archive/2012/01/11/csharp-expression-trees-create-instance-from-type-extension-method.aspx ,核心代碼以下緩存
public static Func<string, T> GetExpression<T>() { var argumentType = new[] { typeof(string) }; // Get the Constructor which matches the given argument Types: var constructor = typeof(T).GetConstructor( BindingFlags.Instance | BindingFlags.Public, null, CallingConventions.HasThis, argumentType, new ParameterModifier[0]); // Get a set of Expressions representing the parameters which will be passed to the Func: var lamdaParameterExpressions = GetLambdaParameterExpressions(argumentType).ToArray(); // Get a set of Expressions representing the parameters which will be passed to the constructor: var constructorParameterExpressions = GetConstructorParameterExpressions( lamdaParameterExpressions, argumentType).ToArray(); // Get an Expression representing the constructor call, passing in the constructor parameters: var constructorCallExpression = Expression.New(constructor, constructorParameterExpressions); // Compile the Expression into a Func which takes three arguments and returns the constructed object: var constructorCallingLambda = Expression .Lambda<Func<string, T>>(constructorCallExpression, lamdaParameterExpressions) .Compile(); return constructorCallingLambda; } private static IEnumerable<ParameterExpression> GetLambdaParameterExpressions(Type[] argumentTypes) { for (int i = 0; i < argumentTypes.Length; i++) { yield return Expression.Parameter(typeof(object), string.Concat("param", i)); } } private static IEnumerable<UnaryExpression> GetConstructorParameterExpressions( ParameterExpression[] lamdaParameterExpressions, Type[] constructorArgumentTypes) { for (int i = 0; i < constructorArgumentTypes.Length; i++) { // Each parameter passed to the lambda is of type object, so we need to convert it into // the appropriate type for the constructor: yield return Expression.Convert(lamdaParameterExpressions[i], constructorArgumentTypes[i]); } }
試試有何提高:app
static void Main(string[] args) { var t = typeof (A); var count = 10000000; var expression = GetExpression<A>(); var ts2 = Timer.Time(() => { var o = expression.Invoke("sss"); }, count); var ts= Timer.Time(() => { var o = Activator.CreateInstance(t, "sss"); }, count); var ts3 = Timer.Time(() => { var o = new A("SSS"); }, count); Console.WriteLine("{0}:{1} ", "Direct", ts3.Milliseconds); Console.WriteLine("{0}:{1}", "Activator.CreateInstance", ts.Milliseconds); Console.WriteLine("{0}:{1}", "Expression", ts2.Milliseconds); Console.ReadLine(); }
結果:函數
使用Expression代替Activator.CreateInstance加快對象建立速度。另外使用Expression&Delegate.CreateDelegate代替傳統C#反射加速屬性和方法的調用.net
參考:htm
http://www.cnblogs.com/artech/archive/2011/03/26/Propertyaccesstest.htmlblog