Как проверить, предоставляет ли тип конструктор без параметров? - PullRequest
92 голосов
/ 13 января 2011

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

Ответы [ 8 ]

154 голосов
/ 13 января 2011

Класс Type - это отражение.Вы можете сделать:

Type theType = myobject.GetType(); // if you have an instance
// or
Type theType = typeof(MyObject); // if you know the type

var constructor = theType.GetConstructor(Type.EmptyTypes);

Он вернет ноль, если конструктор без параметров не существует.


Если вы также хотите найти частные конструкторы, используйте немного более длинный:

var constructor = theType.GetConstructor(
  BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, 
  null, Type.EmptyTypes, null);

Существует предостережение для типов значений, которым не разрешено иметь конструктор по умолчанию .Вы можете проверить тип значения, используя свойство Type.IsValueType, и создать экземпляры, используя Activator.CreateInstance(Type);

13 голосов
/ 23 апреля 2013
type.GetConstructor(Type.EmptyTypes) != null

потерпит неудачу в течение struct с. Лучше продлить его:

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

Успешен, поскольку даже enum s имеет конструктор по умолчанию без параметров. Также немного ускоряется для типов значений, так как вызов отражения не выполняется.

12 голосов
/ 13 января 2011

Да, вы должны использовать отражение. Но вы уже делаете это, когда используете GetType()

Что-то вроде:

var t = x.GetType();
var c = t.GetConstructor(new Type[0]);
if (c != null) ...
8 голосов
/ 13 января 2011

Это должно работать:

   myClass.GetType().GetConstructors()
                    .All(c=>c.GetParameters().Length == 0)
4 голосов
/ 14 января 2011

В зависимости от вашей ситуации вы также можете использовать ограничение общего типа:

public void DoSomethingWith<T>(T myObject) where T:new() {...}

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

Конечно, если тип действительно известен только во время выполнения (т. е. вы используете Activator.CreateInstance () для создания экземпляра объекта на основе строки или составного типа), тогда это не поможетвы.Я обычно использую отражение в качестве абсолютного последнего варианта, потому что как только вы перейдете на динамическую землю, вам в значительной степени придется остаться на динамической земле;обычно сложно или даже сложнее динамически создать что-то, а затем начать работать со статически.

1 голос
/ 26 марта 2019

Если кого-то интересует «официальная» версия, через .NET Reflector :

можно найти следующее: System.Activities.Presentation.TypeUtilities
in System.Activities.Presentation.dll, версия = 4.0.0.0

public static bool CanCreateInstanceUsingDefaultConstructor(this Type t) => 
                t.IsValueType || !t.IsAbstract && t.GetConstructor(Type.EmptyTypes) != null;

Обратите внимание на проверку для t.IsAbstract, которая не упоминается в других разделах этого документа.стр.

Вы также можете расширить вызов GetConstructor следующим образом, если вы хотите микрооптимизировать один кадр стека:

…t.GetConstructor(BindingFlags.Public|BindingFlags.Instance, null, Type.EmptyTypes, null)…
1 голос
/ 12 ноября 2015

Мне нужно было посчитать конструкторы с только необязательными параметрами, такими же, как у конструкторов без параметров. Для этого:

myClass.GetType().GetConstructors()
    .All(c => c.GetParameters().Length == 0 || c.GetParameters().All(p => p.IsOptional))
1 голос
/ 13 января 2011

Да, вы должны использовать отражение.

object myObject = new MyType();
Type type = myObject.GetType();
ConstructorInfo conInfo = type.GetConstructor(new Type[0]);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...