Наиболее эффективный способ получения стандартного конструктора типа

Каков наиболее эффективный способ получить конструктор по умолчанию (т.е. конструктор экземпляра без параметров) System.Type?

Я думал что-то вроде строк ниже, но кажется, что должен быть более простой и эффективный способ сделать это.

Type type = typeof(FooBar)
BindingFlags flags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance;
type.GetConstructors(flags)
    .Where(constructor => constructor.GetParameters().Length == 0)
    .First();

Ответ 1

type.GetConstructor(Type.EmptyTypes)

Ответ 2

Если вы действительно нуждаетесь объект ConstructorInfo, см. ответ Курта Хагенлохера.

С другой стороны, если вы действительно просто пытаетесь создать объект во время выполнения с System.Type, см. System.Activator.CreateInstance - это не только надежное будущее (активатор обрабатывает больше деталей, чем ConstructorInfo.Invoke), он также намного менее уродлив.

Ответ 3

Если у вас есть общий тип типа, тогда ответ Джеффа Бриджмена является лучшим. Если у вас есть только объект типа, представляющий тип, который вы хотите построить, вы можете использовать Activator.CreateInstance(Type), как предложил Алекс Лайман, но мне сказали, что он медленный (я не профилировал его лично, хотя).

Однако, если вы очень часто строите эти объекты, существует более красноречивый подход с использованием динамически скомпилированных выражений Linq:

using System;
using System.Linq.Expressions;

public static class TypeHelper
{
    public static Func<object> CreateDefaultConstructor(Type type)
    {
        NewExpression newExp = Expression.New(type);

        // Create a new lambda expression with the NewExpression as the body.
        var lambda = Expression.Lambda<Func<object>>(newExp);

        // Compile our new lambda expression.
        return lambda.Compile();
    }
}

Просто позвоните делегату, который был возвращен вам. Вы должны кэшировать этот делегат, потому что постоянная перекомпиляция выражений Linq может быть дорогостоящей, но если вы кешируете делегат и повторно используете его каждый раз, это может быть очень быстро! Я лично использую статический словарь поиска, индексированный по типу. Эта функция пригодится, когда вы имеете дело с сериализованными объектами, где вы можете знать только информацию типа.

ПРИМЕЧАНИЕ. Это может быть неудачно, если тип не является конструктивным или не имеет конструктора по умолчанию!

Ответ 4

Если вы хотите, чтобы конструктор по умолчанию создавал экземпляр класса и получает тип в качестве типичного параметра типа для функции, вы можете сделать следующее:

T NewItUp<T>() where T : new()
{
   return new T();
}

Ответ 5

вы бы хотели попробовать FormatterServices.GetUninitializedObject(Type) это лучше, чем Activator.CreateInstance

Однако этот метод не вызывает конструктор объекта, поэтому, если вы устанавливаете исходные значения там, это не сработает Проверьте MSDN для этой вещи http://msdn.microsoft.com/en-us/library/system.runtime.serialization.formatterservices.getuninitializedobject.aspx

здесь есть другой путь http://www.ozcandegirmenci.com/post/2008/02/Create-object-instances-Faster-than-Reflection.aspx

однако это не удается, если объект имеет конструкторы параметризации

Надеюсь, что это поможет