我正在尝试改善我们的应用程序的性能。我们有很多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();
}

注意new约束。叫什么
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/

10-10 04:37