Самый эффективный способ получить конструктор по умолчанию типа - PullRequest
65 голосов
/ 27 сентября 2008

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

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

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

Ответы [ 5 ]

124 голосов
/ 27 сентября 2008
type.GetConstructor(Type.EmptyTypes)
29 голосов
/ 27 сентября 2008

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

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

2 голосов
/ 09 июля 2013

Если у вас есть параметр универсального типа, то ответ Джеффа Бриджмена - лучший. Если у вас есть только объект Type, представляющий тип, который вы хотите создать, вы можете использовать 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 может быть дорогой, но если вы кэшируете делегат и повторно используете его каждый раз, это может быть очень быстро! Я лично использую статический словарь поиска, проиндексированный по типу. Эта функция полезна, когда вы имеете дело с сериализованными объектами, где вы можете знать только информацию типа.

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

0 голосов
/ 16 апреля 2013

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

T NewItUp<T>() where T : new()
{
   return new T();
}
0 голосов
/ 27 сентября 2008

вы хотите попробовать 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

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...