2013-05-13 5 views
2

Так что я не нашел ничего изящного решения для этого, будь то поиск в googling или во время stackoverflow. Я предполагаю, что у меня есть очень специфическая ситуация в моих руках, так или иначе, вот так:C# - Возвращаемые значения по умолчанию для свойств null, когда родительские свойства этих свойств могут быть или не могут быть нулевыми.

У меня есть структура объекта, с которой у меня нет контроля, потому что я получаю эту структуру из внешнего WS. Это довольно огромный объект с различными уровнями полей и свойств, и эти поля и свойства могут или не могут быть нулевыми на любом уровне. Вы можете думать об этом объекте как анемичной модели, у него нет поведения, просто состояние.

Для целей данного вопроса, я дам вам упрощенный образец, который имитирует мою ситуацию:

Class A 
    PropB1 
    PropC11 
     PropLeaf111 
    PropC12 
     PropLeaf112 
    PropB2 
    PropC21 
     PropLeaf211 
    PropC22 
     PropLeaf221 

Таким образом, на протяжении всего моего кода у меня есть доступ к ряду этих свойств, в разных уровнях, чтобы сделать математику, чтобы рассчитать то, что мне нужно. В основном для каждого типа вычислений, которые я должен выполнить, я должен проверить каждый уровень свойств, которые мне нужны, чтобы проверить, не является ли он нулевым, и в этом случае я бы возвращал (десятичный) 0 или любое другое значение по умолчанию в зависимости от бизнес-логики.

Пример из математики, что я должен сделать с ним:

var value = 0; 
if (objClassA.PropB1 != null && objClassA.PropB1.PropC11 != null) { 
    var leaf = objClassA.PropB1.PropC11.PropLeaf111; 
    value = leaf.HasValue ? leaf.Value : value; 
} 

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

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

  1. Создание методов для сбора свойств, где бы абстрактные любые необходимые проверки, или логика, чтобы получить значения по умолчанию. Недостатком является то, что у него, по-моему, был бы достаточно дублированный код, так как проверки и значения по умолчанию были бы похожими для некоторых групп полей.
  2. Создайте единый общий метод, в котором он получает объект, и функцию lamba, которая получает доступ к требуемому полю. Этот метод попытается выполнить функцию и вернуть ее результат, а в случае исключения NullReferenceException будет возвращено значение по умолчанию. Яркая сторона этого заключается в том, что он действительно общий, мне просто нужно передать lambdas для доступа к свойствам, и метод будет обрабатывать любую проблему. Недостатком этого является то, что я использую try-> catch для управления логикой, что не является целью этого, и код может выглядеть запутанным для других программистов, которые в конечном итоге будут поддерживать его.
  3. Null Object Pattern, это было бы самое элегантное решение, я думаю. У него были бы все хорошие моменты, если бы это был обычный случай. Но дело в том, что для этой структуры можно предоставить Null Objects. Чтобы дать немного больше контекста, программное обеспечение, над которым я работаю, интегрируется с государственными службами и структура, с которой я работаю, которая находится в спецификациях правительства, имеет некоторые поля, где null имеет некоторый смысл, который отличается от значение по умолчанию, например «0». Кроме того, эта спецификация время от времени меняется, и классы генерируются снова, и для последующей обработки, которую мне нужно было бы сделать для создания Null Objects, также потребуется техническое обслуживание, что для меня немного опасно.

Надеюсь, что я сделал себе достаточно ясно.

Заранее благодарен.

Решение

Это ответ о том, как я решил мою проблему, на основе принятого ответа.

Я совершенно новичок в C#, и такая связь, которая была связана, действительно помогла мне придумать элегантное решение во многих аспектах. У меня все еще есть проблема, которая зависит от того, где выполняется код, он использует .NET 2.0, но я также нашел решение этой проблемы, где я могу несколько определить методы расширения: https://stackoverflow.com/a/707160/649790

И для самого решения я нашел это один из лучших: http://www.codeproject.com/Articles/109026/Chained-null-checks-and-the-Maybe-monad

Я могу в принципе получить доступ к свойствам таким образом, и просто делать математику:

objClassA.With(o => o.PropB1).With(o => PropC11).Return(o => PropLeaf111, 0); 

Для каждого свойства, что мне нужно. Он по-прежнему не просто:

objClassA.PropB1.PropC11.PropLeaf111 

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

Еще раз спасибо.

+3

Обсуждение здесь http://stackoverflow.com/q/2080647/2300730 связано с вашим вопросом, некоторые советы оттуда могут быть полезны – jure

+0

Спасибо, что сообщение обсуждает некоторые аспекты дизайна, которые очень интересны, также я нашел «Закон Деметры», что я не был знаком с – JeanK

ответ

4

Существует стратегия борьбы с этим, включая "Maybe" Monad.

В основном это работает, обеспечивая «свободный» интерфейс, где цепочка свойств прерывается с помощью null где-то вдоль цепочки.

Смотрите здесь для примера: http://smellegantcode.wordpress.com/2008/12/11/the-maybe-monad-in-c/

А также здесь:

http://www.codeproject.com/Articles/109026/Chained-null-checks-and-the-Maybe-monad http://mikehadlow.blogspot.co.uk/2011/01/monads-in-c-5-maybe.html

Это связано, но не совсем то же самое, что вы, кажется, нужно; однако, возможно, это может быть адаптировано к вашим потребностям. Концепции довольно фундаментальны.