Как получить конструктор по умолчанию, когда параметры являются необязательными - PullRequest
9 голосов
/ 07 апреля 2011

Я использую Type.GetConstructor(Type.EmptyTypes), чтобы получить конструктор по умолчанию для класса.Это работает, если у класса есть конструктор по умолчанию без параметров (class A).Но это не работает, если у класса есть конструктор со всеми необязательными параметрами (class B).Программа не знает, какие необязательные параметры, потому что ей нужен только конструктор по умолчанию.Какие заявления можно использовать, чтобы они работали в обоих случаях?Спасибо, благодарю за любую помощь!

public class A
{
    public A() {}
} 

public class B
{
    public B(int i = 0, string str = "") {}
}

Ответы [ 5 ]

6 голосов
/ 07 апреля 2011

Скажите, у меня есть следующий класс:

public class SomeClass
{
    public SomeClass()
    {

    }

    public SomeClass(int x)
    {
    }

    public SomeClass(int x = 0, int y = 0)
    {

    }
}

По сути, вы запрашиваете запрос, который найдет конструкторы, которые соответствуют конструкторам 1 и 3 выше? Если это так, используйте это:

var constuctors = typeof(SomeClass).GetConstructors()
            .Where(x => x.GetParameters().Count() == 0 
                    ||  x.GetParameters().Count(param => param.GetCustomAttributes(typeof(OptionalAttribute), false).Count() > 0) == x.GetParameters().Count());    

Невероятно неприятный запрос, но он выполняет свою работу, возвращая только 1 и 3 выше.

3 голосов
/ 07 апреля 2011

Проблема в том, что компилятор C # выдает это:

public class B
{
    // Methods
    public B([Optional, DefaultParameterValue(0)] int i, [Optional, DefaultParameterValue("")] string str)
    {
    }
}

Должно работать что-то вроде ниже:

public static class TypeHelper {
    public static ConstructorInfo GetDefaultConstructor<TType>() {
        var type = typeof(TType);
        return type.GetDefaultConstructor();
    }

    public static ConstructorInfo GetDefaultConstructor(this Type type) {
        if(type == null) throw new ArgumentNullException("type");
        var constructor = type.GetConstructor(Type.EmptyTypes);
        if(constructor == null) {
            var ctors = 
                from ctor in type.GetConstructors()
                let prms = ctor.GetParameters()
                where prms.All(p=>p.IsOptional)
                orderby prms.Length
                select ctor;                        
            constructor = ctors.FirstOrDefault();
        }
        return constructor;
    }
}
3 голосов
/ 07 апреля 2011

Проблема в том, что необязательные параметры - это не более чем концепция времени компиляции.Вам нужно будет полностью указать конструктор.

var ci = typeof(B).GetConstructor(new [] { typeof(int), typeof(string) });

Вы можете написать вспомогательную функцию, которая будет вызывать конструктор со значениями по умолчанию.Мой пример не такой надежный, как следовало бы, но он должен помочь вам начать.

2 голосов
/ 07 апреля 2011

Проблема в том, что в случае B он не имеет конструктора без параметров.

Необязательные аргументы - это конструкция времени компиляции - в IL это конструктор с 2 параметрами (которые помечены атрибутами). Таким образом, по умолчанию в Reflection нет конструктора по умолчанию.

0 голосов
/ 07 апреля 2011

Если конструктор или любой другой метод имеет необязательные аргументы, это не приводит к тому, что компилятор генерирует несколько версий метода. Вместо этого он генерирует единственный метод, который имеет все указанные параметры. Значения по умолчанию кодируются в атрибутах, прикрепленных к сигнатуре метода. Они используются на сайте вызова, чтобы сделать их значения необязательными.

Так что здесь нет конструктора по умолчанию, а только один с двумя параметрами

...