c# - 快速创建对象而不是 Activator.CreateInstance(type)

标签 c# reflection reflection.emit activator createinstance

我正在努力提高我们应用程序的性能。我们有很多 Activator.CreateInstance 调用导致了一些问题。

我们基于接口(interface) (ITabDocument) 实例化了很多类,环顾四周后我想到了使用以下代码:

该代码并不比使用我们已有的 Activator.CreateInstance 代码好(实际上稍微慢一点)。

    public static Func<T> CreateInstance<T>(Type objType) where T : class, new()
    {
        var dynMethod = new DynamicMethod("DM$OBJ_FACTORY_" + objType.Name, objType, null, objType);
        ILGenerator ilGen = dynMethod.GetILGenerator();
        ilGen.Emit(OpCodes.Newobj, objType.GetConstructor(Type.EmptyTypes));
        ilGen.Emit(OpCodes.Ret);
        return (Func<T>)dynMethod.CreateDelegate(typeof(Func<T>));
    }

我想知道这是为什么,我所做的就是:

ITabDocument document = CreateInstance<ITabDocument>(Type.GetType("[Company].Something"));

是否有更好的创建对象的方法来帮助完成上述任务?当您不确定具体类型时,这有点困难。

最佳答案

我在这些之间做了一些基准测试(我会写下最低限度的细节):

public static T Instance() //~1800 ms
{
    return new T();
}

public static T Instance() //~1800 ms
{
    return new Activator.CreateInstance<T>();
}

public static readonly Func<T> Instance = () => new T(); //~1800 ms

public static readonly Func<T> Instance = () => 
                                 Activator.CreateInstance<T>(); //~1800 ms

//works for types with no default constructor as well
public static readonly Func<T> Instance = () => 
               (T)FormatterServices.GetUninitializedObject(typeof(T)); //~2000 ms


public static readonly Func<T> Instance = 
     Expression.Lambda<Func<T>>(Expression.New(typeof(T))).Compile();  
     //~50 ms for classes and ~100 ms for structs

正如 CD 所说,编译表达式是最快的,而且有很大的优势。除 (T)FormatterServices.GetUninitializedObject(typeof(T)) 之外的所有方法 仅适用于具有默认构造函数的类型。

当每个泛型都有一个静态类时,缓存编译后的结果委托(delegate)是微不足道的。喜欢:

public static class New<T> where T : new()
{
    public static readonly Func<T> Instance = Expression.Lambda<Func<T>>
                                              (
                                               Expression.New(typeof(T))
                                              ).Compile();
}

请注意 约束。随叫随到

MyType me = New<MyType>.Instance();

除了第一次将类加载到内存中外,执行速度最快。

为了拥有一个可以处理带默认构造函数和不带默认构造函数的两种类型的类,我采用了混合方法,from here :

public static class New<T>
{
    public static readonly Func<T> Instance = Creator();

    static Func<T> Creator()
    {
        Type t = typeof(T);
        if (t == typeof(string))
            return Expression.Lambda<Func<T>>(Expression.Constant(string.Empty)).Compile();

        if (t.HasDefaultConstructor())
            return Expression.Lambda<Func<T>>(Expression.New(t)).Compile();

        return () => (T)FormatterServices.GetUninitializedObject(t);
    }
}

public static bool HasDefaultConstructor(this Type t)
{
    return t.IsValueType || t.GetConstructor(Type.EmptyTypes) != null;
}

也将以高效的方式处理值类型。

请注意 (T)FormatterServices.GetUninitializedObject(t) 对于 string 将失败。因此,对字符串进行特殊处理以返回空字符串。

关于c# - 快速创建对象而不是 Activator.CreateInstance(type),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6582259/

相关文章:

c# - 如何连接到 .NET 框架内的 MySQL 数据库?

c# - 通知 Visual Studio 通过反射调用的代码

c# - 表示为细长三角形的线在 3D 中不可见?

java - 我可以使用反射在类中添加新字段吗

c# - 在新应用程序域上创建动态程序集

c# - 如何使用表达式生成此属性实现而不是发出 IL?

c# - 将目标框架从 v4.0 更改为 v3.5 后找不到命名空间

c# - 枚举反射程序集中的集合需要空引用检查吗?

java - 在Java中反射数组

c# - 是否可以在运行时向现有类添加方法?为什么或者为什么不?