日期:2014-05-18 浏览次数:20946 次
需求:使用泛型创建有参数的对象(性能上考虑,不使用反射创建)。
使用泛型创建无参(默认)构造函数的对象可以用
where :T ,new()
new T();
来实现,但是如果构造函数带有参数怎么办呢?
于是就写了一下一段代码:
这里使用了Expression 和 LambdaExpression,目的是为了生成对应类构造函数的委托
,所以第一次调用会相对慢一点,随后调用就像直接new一样快,适合多次调用情况。
?
?
?
?
using System; using System.Linq.Expressions; using System.Reflection; namespace XXX { /// <summary> /// ObjectCreator class used to create object at runtime. /// </summary> public class ObjectCreator<T> { #region Singleton private ObjectCreator() { } public static ObjectCreator<T> Instance { get { return Nested.m_instance; } } private class Nested { static Nested() { } internal static readonly ObjectCreator<T> m_instance = new ObjectCreator<T>(); } #endregion private ObjectActivator m_rowCreatedActivator = null; /// <summary> /// Constructor of delegate /// </summary> /// <typeparam name="T">Type</typeparam> /// <param name="args">arguments of Constructor</param> /// <returns>Type</returns> private delegate T ObjectActivator(params object[] args); public T Create(Type[] types, params object[] args) { if (null == m_rowCreatedActivator) { m_rowCreatedActivator = ObjectCreator<T>.Instance.GetActivator(typeof(T).GetConstructor(types)); } return m_rowCreatedActivator(args); } /// <summary> /// Create object type at runtime. /// </summary> /// <typeparam name="T">Type</typeparam> /// <param name="ctor">ConstructorInfo of Type</param> /// <returns>Constructor of delegate</returns> private ObjectActivator GetActivator(ConstructorInfo ctor) { ParameterInfo[] paramsInfo = ctor.GetParameters(); //create a single param of type object[] ParameterExpression param = Expression.Parameter(typeof(object[]), "args"); Expression[] argsExp = new Expression[paramsInfo.Length]; //pick each arg from the params array //and create a typed expression of them for (int i = 0; i < paramsInfo.Length; i++) { Expression index = Expression.Constant(i); Type paramType = paramsInfo[i].ParameterType; Expression paramAccessorExp = Expression.ArrayIndex(param, index); Expression paramCastExp = Expression.Convert(paramAccessorExp, paramType); argsExp[i] = paramCastExp; } //make a NewExpression that calls the //ctor with the args we just created NewExpression newExp = Expression.New(ctor, argsExp); //create a lambda with the New //Expression as body and our param object[] as arg LambdaExpression lambda = Expression.Lambda(typeof(ObjectActivator), newExp, param); //compile it ObjectActivator compiled = (ObjectActivator)lambda.Compile(); return compiled; } } }