经常用反射创建对象的朋友一定用过Activator.CreateInstance方法,这段时间在学习IL用Emit也实现了这样一个功能,也支持多不同参数的构造。
不过动太方法的key构造并不理想所以在性能上有所损耗,但其性能还是优胜于Activator.CreateInstance方法。
以下是测试代码和工厂代码
public delegate object CreateInstanceHandler(object[] parameters);
public class Program

{
public Program()

{
}
public Program(int i)

{
}
public Program(int i, string name)

{
}
static void Main(string[] args)

{

Program p;
p = Activator.CreateInstance<Program>();
p = CreateObjectFactory.CreateInstance<Program>();

p = (Program)Activator.CreateInstance(typeof(Program), new object[]
{ 2 });

p = CreateObjectFactory.CreateInstance<Program>(new object[]
{ 2 });

p = (Program)Activator.CreateInstance(typeof(Program), new object[]
{ 2, "henry" });

p = CreateObjectFactory.CreateInstance<Program>(new object[]
{ 2, "henry" });
System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();
for (int i = 0; i < 10; i++)

{
sw.Reset();
sw.Start();
p = Activator.CreateInstance<Program>();

p = (Program)Activator.CreateInstance(typeof(Program), new object[]
{ 2 });

p = (Program)Activator.CreateInstance(typeof(Program), new object[]
{ 2, "henry" });
sw.Stop();
Console.WriteLine("Reflection:\t" + sw.Elapsed.TotalMilliseconds);

sw.Reset();
sw.Start();
p = CreateObjectFactory.CreateInstance<Program>();

p = CreateObjectFactory.CreateInstance<Program>(new object[]
{ 2 });

p = CreateObjectFactory.CreateInstance<Program>(new object[]
{ 2, "henry" });
sw.Stop();
Console.WriteLine("Emit:\t" + sw.Elapsed.TotalMilliseconds);

}
Console.Read();
}
}
public class CreateObjectFactory

{
public static T CreateInstance<T>()

{
return CreateInstance<T>(null);
}
static Dictionary<string, CreateInstanceHandler> mHandlers = new Dictionary<string, CreateInstanceHandler>();

public static T CreateInstance<T>(params object[] parameters)

{
Type objtype = typeof(T);
Type[] ptypes = GetParameterTypes(parameters);
string key = typeof(T).FullName + "_" + GetKey(ptypes);
if (!mHandlers.ContainsKey(key))

{
CreateHandler(objtype, key, ptypes);
}
return (T)mHandlers[key](parameters);

}
static void CreateHandler(Type objtype, string key, Type[] ptypes)

{
lock (typeof(CreateObjectFactory))

{
if (!mHandlers.ContainsKey(key))

{

DynamicMethod dm = new DynamicMethod(key, typeof(object), new Type[]
{ typeof(object[]) }, typeof(CreateObjectFactory).Module);
ILGenerator il = dm.GetILGenerator();
ConstructorInfo cons = objtype.GetConstructor(ptypes);

il.Emit(OpCodes.Nop);
for (int i = 0; i < ptypes.Length; i++)

{
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Ldc_I4, i);
il.Emit(OpCodes.Ldelem_Ref);
if (ptypes[i].IsValueType)

{
il.Emit(OpCodes.Unbox_Any, ptypes[i]);
}
else

{
il.Emit(OpCodes.Castclass, ptypes[i]);
}


}
il.Emit(OpCodes.Newobj, cons);
il.Emit(OpCodes.Ret);
CreateInstanceHandler ci = (CreateInstanceHandler)dm.CreateDelegate(typeof(CreateInstanceHandler));
mHandlers.Add(key, ci);

}
}
}
static Type[] GetParameterTypes(params object[] parameters)

{
if (parameters == null)
return new Type[0];
Type[] values = new Type[parameters.Length];
for (int i = 0; i < parameters.Length; i++)

{
values[i] = parameters[i].GetType();
}
return values;
}
static string GetKey(params Type[] types)

{
if (types == null || types.Length == 0)
return "null";
return string.Concat(types);
}

}
posted on 2008-05-23 21:17
henry 阅读(1205)
评论(4) 编辑 收藏 所属分类:
Emit