System.NullReferenceException с предложением выбора - PullRequest
1 голос
/ 23 февраля 2012

Здравствуйте, любимое Сообщество: D

сейчас я работаю над своим первым большим проектом и немного застрял. Я пытаюсь подтвердить ввод.

Поэтому я использую эту функцию:

public static Validatable<string> RequiredOr(this Validatable<string> that, Func<Validatable<string>, bool> func)
{
    return that.DoEvaluate && !(func(that) || that.Value != null)
            ? that.Error(ML.Get("Validation", "IsRequired"))
            : that;
}

Для нормальной проверки я использую это:

public Validatable<TProperty> Validate<TProperty>(
        Expression<Func<TEntity, TProperty>> expr)
    {
        return new Validatable<TProperty>(
            new ErrorTrackerWrapper(ErrorTracker, expr.Body), expr.Compile()(Value));
    }

И эта часть для вызова функции «RequiredOr»:

var header = from name in v.Validate(it => it.Name).Required().MaxLength(Constants.String.NameLength)
                     from startDate in v.Validate(it => it.StartDate).Required().After(DateTime.Today)
                     from endDate in v.Validate(it => it.EndDate).Required().After(DateTime.Today)
                     from endTime in v.Validate(it => it.EndTime).BlockErrors().Required().ReplaceIfInvalid(new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day, 23, 30, 0))
                     from requestedCurrency in v.Validate(it => it.RequestedCurrency).Required()
                     from language1 in v.Validate(it => it.Language1).Required()
                     from language2 in v.Validate(it => it.Language2)
                     from language3 in v.Validate(it => it.Language3)
                     from hasMoreInformation in v.Validate(it => it.HasMoreInformation)
                     // TODOJP: If "hasMoreInformation" is true, then "moreInformationEmail" has to be required.
                     from moreInformationEmail in v.Validate(it => it.MoreInformationEmail).IsEmail()//.RequiredOr(p => !hasMoreInformation)
                     from isAnonymous in v.Validate(it => it.IsAnonymous)
                     select new AnnouncementHeader(
                        currentUser,
                        type,
                        name,
                        startDate,
                        endDate.SetTime(new Time(endTime.Hour, endTime.Minute)),
                        isAnonymous,
                        infoField,
                        requestedCurrency,
                        language1,
                        language2,
                        language3,
                        hasMoreInformation,
                        moreInformationEmail);

Пока что это правильно, но кое-что, как он говорит мне, что hasMoreInformation в части RequiredOr является NullReferenceException.

Мне удалось отследить ошибку до функции «RequiredOr».

Я хотел бы проверить, является ли "HasMoreInformation" истинным или нет, а затем установить поле как "Обязательное" или нет.

Я надеюсь, вы понимаете, что я пытаюсь вам сказать. И большое спасибо за вашу помощь.

1 Ответ

0 голосов
/ 23 февраля 2012

С потенциально нулевым объектом, вы должны проверить, существует ли поле, прежде чем проверять, верно ли оно.Следствием нарушения правила является исключение null ref.Вот как это работает.

Если элемент обнуляем, всегда есть потенциал, что он будет нулевым.Вы можете сделать это не так, если вы зададите значение по умолчанию, но тогда значение по умолчанию должно иметь одно значение и не означать, что «это может быть значение по умолчанию» и «оно может быть явно установлено пользователем».

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

Поскольку у меня очень мало контекста, я бы рекомендовал записать это вДлинная форма для решения проблемы.Затем вы можете переосмыслить в стиле отложенного выполнения (LINQ).Я говорю это потому, что вы, кажется, хотите выбрать только действительный, когда элемент не равен NULL И что-то еще, что не указано явно (на основании комментария о проверке, который требуется после).Пройдите через эту проблему, прежде чем LINQ ее решит.

NEW: Все еще придерживайтесь последней строки о решении перед LINQ-решением (и я включу здесь все формы отложенного выполнения, а не только LINQ).

Если бы я не тратил много времени на утверждение, у вас есть несколько LINQ и несколько методов расширения (гибкий синтаксис с цепочечными методами, бла, бла).Все это отложенное исполнение.Если бы вы опускали символы и просматривали стек, вы могли бы обнаружить, что порядок отложенного выполнения является частью проблемы.часто это единственный способ отладить кучу абстракций.(Да, я видел вложенный оператор LINQ из 47 строк с указателями функций и методами расширения)

Когда вы используете стиль плавного программирования, вы, по сути, запускаете шаблон псевдо-IoC, как метод, наиболее удаленный отправо проходит до следующего метода, пока вы не пройдете весь путь влево.Очень плохое аналогичное объяснение, так что я, скорее всего, поправлюсь, но вы работаете с указателями на функции, чтобы поддерживать поток в правильном методе.Пример:

Colonel.Sanders.Loves.Chicken ("fried");

Указатели функций, методы расширения и RX, о боже!Довольно аккуратные вещи с философской точки зрения, но склонные к плохому джиу-джеджу, если вы действительно не понимаете, как это работает.Это часто делает для очень ясного синтаксиса, но создает кошмар отладки.

Если вы в дальнейшем будете придерживаться заявления LINQ, чтобы выбрать планы питания или рестораны быстрого питания, в конечном итоге вы получите много отложенного липучка, поступающего со всех сторон.И, если один бит не в правильном порядке, некоторый код запускается до необходимого предшественника.Поскольку в LINQ и методах расширения используется другая методология, их смешивание увеличивает вероятность запуска битов в неправильном порядке.А отладка с помощью символов часто является единственным способом взлома, поскольку весь блок отложенных абстракций «компилируется» во время выполнения.

Итак, чтобы завершить этот длинный пост, вам нужно либо: а) выполнить отладку, либовыясните, почему вы получаете нулевой ref (скорее всего, некоторые ошибки в вызовах в вашем стеке отложенного выполнения) или б) сначала решите проблему с помощью неотложенных методологий (или, возможно, запускаете один бит отложенного goo за раз?).

...