如何使用反射创建高性能.NET类?

时间:2009-07-10 21:57:44

标签: c# .net reflection

好的,所以我们都知道Reflecttion的性能要比“newing”类实例少得多,而且在很多情况下,根据应用程序的要求,这很好。

问题:我们如何使用后期绑定(反射)策略创建高性能.NET类。

我有一个现有的要求,即要求使用反射(CreateInstance)创建类实例,但性能至关重要。在我的情况下,我正在为我们的应用程序中的每个传入SMS消息创建实例。在生产过程中,每天可能很容易超过一百万。

我想听听并分享一些关于如何在不直接引用代码中的类的情况下创建.NET类的想法,例如使用Reflection。我还在想是否有办法以某种方式缓存一个可以改善“创建”时间的类工厂

6 个答案:

答案 0 :(得分:12)

每天100万不是很多;我只是使用Activator.CreateInstance(使用Activator.CreatInstance(Type)进行的快速测试表明,在我的低端笔记本电脑上,它可以在{2}中从Type创建1M对象。

快速创建对象的想法:

  • 使用泛型和: new()约束(零努力)
  • 使用DynamicMethod并编写IL(不是很难)

此处显示new方法的实现(不需要外部: new()约束):ObjectFactory.cs

有关IL示例,请参阅dapper-dot-netil.Emit(OpCodes.Newobj, ...)

答案 1 :(得分:6)

我认为每天只有一百万只用于简单的反思。我相信你是在过度优化,但无论如何,正如你所说,只需使用一个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的实例或配置文件中指定的任何其他类设置一次。< / p>

答案 2 :(得分:5)

一些想法:

  • 一旦发现需要,就保持每个班级的一个实例。然后,而不是CreateInstance,克隆它。
  • 创建第一个实例后,请保留实例的类型。然后使用Activator.CreateInstance(Type)

将实例缓存为克隆或键入Dictionary<string,Type>Dictionary<string,object>

答案 3 :(得分:5)

通常情况下,Jon Skeet是你的朋友。 查看他的博客文章Making reflection fly and exploring delegates

答案 4 :(得分:1)

GREAT!类工厂的方法似乎是去这里的方法。

在第一个请求中使用Assembly.CreateInstance(typeNameString)的组合,然后在工厂中缓存Type

在后续通话中使用Activator.CreateInstance(type)

使用此方法,它比使用本机New运算符慢20%。没什么大不了的!

创建1000万Employee个对象的统计信息如下:

  • 使用new运算符

  • 8秒
  • 使用工厂/类型/缓存方法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;    
}

答案 5 :(得分:0)

定义并实现一个接口,而不是使用反射。