Сделать объект доступным только для одного другого объекта в той же сборке?

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

Обновить

Грег поднял вопрос о проверяемости. Поскольку SqlObjects будет содержать sql, очень специфичный для бизнес-процессов, я не хочу, чтобы они повторно использовались в нескольких объектах бизнеса. (Все основные операции CRUD генерируются кодом) Есть ли способ сделать SqlObjects доступными только для одного бизнес-объекта в бизнес-сборке (как показано yshuditelu и Greg Beech) И предоставить SqlObjects сборке модульного тестирования?


person adam0101    schedule 15.09.2009    source источник


Ответы (4)


Если это тот подход, который вы хотите или должны использовать, вы можете сделать объекты sql частными классами внутри бизнес-объекта.

public class BusinessObject
{
    private class SqlObject { }
}

Кроме того, используя частичные классы, вы можете при желании разделить их на отдельные файлы.

//in one file
public partial class BusinessObject
{
    //business object implementation
}

//in another file
public partial class BusinessObject
{
    private class SqlObject { }
}

Джоэл делает хорошее замечание в комментарии ниже: «SqlObject все еще может наследовать от общего типа, поэтому такие вещи, как информация о подключении, могут быть разделяется между этими «внутренними» классами ». это абсолютно верно и потенциально очень полезно.

В ответ на ваше изменение модульные тесты могут тестировать только общедоступные классы и функции (без использования отражения в ваших тестах). Единственный вариант, который я могу придумать, - это:

  • сделать одну сборку для каждой пары объектов бизнес / sql
  • изменение private class SqlObject на internal class SqlObject
  • затем используйте [InternalsVisibleTo("UnitTestsAssembly")] для проекта

Кроме того, на этом этапе вам не нужно сохранять объект sql как вложенный класс. Вообще говоря, я думаю, что это, вероятно, добавит больше сложности, чем добавленная ценность, но я полностью понимаю, что каждая ситуация индивидуальна, и если ваши требования / ожидания подталкивают вас к этому, я желаю вам всего наилучшего. Лично я думаю, что я бы пошел с тем, чтобы сделать SqlObjects общедоступными (или внутренними с видимыми внутренними компонентами для модульного тестирования) и принять тот факт, что это означает, что классы sql доступны для всех бизнес-классов.

person Timothy Carter    schedule 15.09.2009
comment
Также: SqlObject все еще может наследовать от общего типа, чтобы такие вещи, как информация о подключении, могли совместно использоваться этими внутренними классами. - person Joel Coehoorn; 15.09.2009
comment
Спасибо. Я уже использую частичные классы для генерации кода. Я отделяю sql для внедрения зависимостей. Ваш подход потребует очень небольших изменений в моих шаблонах! - person adam0101; 15.09.2009

Единственный способ сделать это - сделать объект SQL частным вложенным типом, т.е.

public class BusinessObject
{
    private class SqlObject
    {
    }
}

Другое дело, хорошая ли это идея с точки зрения тестируемости ...

person Greg Beech    schedule 15.09.2009
comment
Это хороший аргумент в отношении тестируемости. Есть ли способ сделать это И предоставить класс SqlObject сборке модульного тестирования, но не другим бизнес-объектам? - person adam0101; 16.09.2009

Вы пытаетесь реализовать то, что является Friend Class в C ++. Насколько мне известно, в C # и VB.Net нет ничего эквивалентного. Мое единственное предложение - сделать класс, который вы хотите ограничить, внутренним классом класса, который должен получить к нему доступ.

person Christian Loris    schedule 15.09.2009

Вы также можете работать с двумя сборками (одна для бизнес-объектов и одна для связанных объектов SQL) и использовать внутренний модификатор для каждого класса SQL, а затем использовать [InternalsVisibleTo("BusinessObjectAssembly")] для SQLAssembly.

person weismat    schedule 15.09.2009