Как сделать один класс ответственным за строительство другого класса - PullRequest
0 голосов
/ 13 марта 2020

Я пишу библиотеку классов с классом Application. Класс Application содержит коллекцию объектов Document. Я хочу, чтобы класс Application отвечал за "создание" (конструирование) Document объектов, когда это необходимо. Я не хочу, чтобы я или другие наши разработчики могли произвольно создавать новые Document объекты.

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

Первый способ - это вложить класс Application в класс Document и сделать конструктор Document закрытым, так что только Application класс может получить к нему доступ. Но это не имеет смысла структурно и фактически является противоположностью истинных отношений. Не говоря уже о том, что вложенные c вложенные классы, как правило, не приветствуются.

Другой способ, которым я пытался, - сделать конструктор Document частным, но дать ему "фабричный метод" publi c, который выполняет некоторые действия. проверка, чтобы убедиться, что он действительно был вызван Application. Но это стало очень запутанным, когда я попытался реализовать это.

Я слишком усложняю это? Конечно, обычным делом является то, что кодовая база строится так, что разработчики могут сделать что-то, чего не должны делать? Стоит ли ожидать, что наши разработчики (и я) будем использовать благоразумие и здравый смысл, а не go при создании новых Document объектов, когда они должны получать их из Application вместо этого?

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


Примечание: я нашел эту похожую тему: java - сделать класс только экземпляром из Speci c класс . Но предлагаемое решение было вложенными классами, которые не являются хорошим вариантом по причинам, которые я привел выше.

Ответы [ 4 ]

2 голосов
/ 13 марта 2020

Есть способ сделать это, но он несколько запутан, и я бы этого не делал ...

Вы можете поместить реализацию Document в отдельную сборку и сделать ее конструктором internal ,

Затем поместите класс Application в другую сборку (самостоятельно) и используйте InternalsVisibleTo в сборке документа, чтобы сделать конструктор Document видимым для сборки Application ,

Таким образом, только код в сборке Application или сборке Document сможет создать Document. (Конечно, это можно обойти, просто добавив классы в сборку Application или сборку Document, которые создают экземпляры Document ...)

Хотя я бы на самом деле не хотел Application класс для непосредственного создания экземпляров Document. Я бы хотел абстрагироваться Document за класс IDocument и передать фабричный метод в Application, чтобы использовать его для создания IDocument элементов.

1 голос
/ 13 марта 2020

Нет способа сделать именно то, что вы хотите. Что вы можете сделать, это объявить все конструкторы для класса internal / Friend, и тогда только классы в одной сборке смогут вызывать их. Тогда вам решать, какие типы, объявленные в этой сборке, действительно вызывают эти конструкторы. Если вам нужен только один класс, делайте это только в этом классе. Именно так работает класс DataRow. Заметьте, что вы не можете создать объект DataRow напрямую, но можете сделать это косвенно, используя методы DataTable.NewRow или DataRowCollection.Add?

0 голосов
/ 13 марта 2020

Другим вариантом является использование

[CallerFilePath] string callerFilePath = ""

в качестве параметра в вашем методе (или конструкторе) для проверки, является ли вызывающая сторона из вашего приложения. Тем не менее, это все еще ошибка времени выполнения, а не ошибка компиляции.

Если вы хотите применить во время компиляции, вам нужно переместить оба класса в проект и использовать внутренний конструктор для Document, и publi c метод в приложении.

0 голосов
/ 13 марта 2020

Насколько я знаю, C# не предоставляет классу возможности ограничить свои методы, в данном случае конструктор, быть вызываемыми только из указанных c других классов. Вложение Document в Application и предоставление его другим классам через интерфейс может быть лучшим выбором - см. этот вопрос для примера.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...