好了,大家都知道Reflecttion是很多的时间比“newing”一个类的实例,更少的高性能和这只是罚款根据不同的应用需求很多情况下。
问题:我们如何创建使用后期绑定(反射)战略高性能.NET类。
我有一个现有的要求,即要求类实例使用反射(的CreateInstance)创建,但性能是至关重要的。 在我的情况,我在我们的应用程序的每个传入SMS消息创建实例。 在生产过程中,这可能很容易地超过一百万,每天。
我想听听,分享关于如何创建.NET类的一些想法,而无需使用反射直接引用类的代码,例如。 我也在想,如果有以某种方式缓存类工厂,可以提高“创建”时间的方式
每天100万也不是很多; 我只是用Activator.CreateInstance
(快速测试使用Activator.CreatInstance(Type)
表明,在我的笔记本电脑低就可以从创建1M对象Type
在约2秒)。
在快速创建对象的思考:
- 使用泛型和
: new()
约束(零努力) - 使用
DynamicMethod
和写的IL(不硬)
的的实现new
方法(而不需要: new()
约束外)如下所示: ObjectFactory.cs
。
对于IL例如,参见短小精悍的点网和il.Emit(OpCodes.Newobj, ...)
我不认为每天一百万是太多简单的反射调用。 我相信你是过度优化,但无论如何,正如你所说的,只是用一个单一的创建工厂类Activator.CreateInstance
呼叫和高速缓存的那一个。 实际情况下将使用被创建CreateInstance()
返回的对象上的方法调用。
public interface IClassFactory {
IClass CreateInstance();
}
public interface IClass {
// your actual class interface.
}
public class DefaultClassFactory : IClassFactory {
public IClass CreateInstance() {
return new DefaultClass(); // the implementation class
}
}
某处你就会有一个static
类型的字段IClassFactory
,你会用实例设置一次DefaultClassFactory
或配置文件或任何指定的任何其他类。
一些想法:
- 保持每个类的一个实例周围,一旦你找到你需要它。 然后,代替的CreateInstance的,克隆它。
- 一旦你创建的第一个实例,保持周围实例的类型。 然后使用Activator.CreateInstance(类型)
缓存实例克隆或在类型Dictionary<string,Type>
或Dictionary<string,object>
。
由于通常情况下,乔恩斯基特是你的朋友在这里。 看他的博客文章制作反射飞翔和探索代表
大! 类工厂的做法似乎是去这里的路。
使用的组合Assembly.CreateInstance(typeNameString)
上的第一个请求,则高速缓存Type
在出厂。
在随后的调用使用Activator.CreateInstance(type)
。
使用这种方法,它比使用本地运营商新的慢20%。 没什么大不了的存在!
10级亿打造统计Employee
的对象如下:
8秒使用new
操作者
10秒使用工厂/类型/高速缓存的方法。
下面是示例代码,如果有人有兴趣:
private IEmployee CachedClassFactory()
{
if(_typeCache == null)
{
// This is a one time hit to load the type into the cache
string typeName = "ClassFactoryTest.Employee";
string assemblyName = "ClassFactoryTest";
Assembly assembly = Assembly.Load(assemblyName);
IEmployee employee = assembly.CreateInstance(typeName) as IEmployee;
_typeCache = employee.GetType();
}
IEmployee instance = Activator.CreateInstance(_typeCache) as IEmployee;
instance.FirstName = "Raiford";
instance.LastName = "Brookshire";
instance.Birthdate = DateTime.Now.AddYears(-35);
instance.Age = 35;
return instance;
}