[.NET] FamilyAndAssembly
Вот расскажитека мне.
class BaseClass
{
protected BaseClass {}
}
class Derived1
{
protected Derived1 : base {}
}
class Factory
{
BaseClass CreateInstance
{
if (...) return new Derived1;
...
}
}
Нутаквот. Какой аксессмодифайер ставить на конструкторы DerivedN ? Если протектед, то их нельзя вызвать из фабрики. Если НЕ протектед, то их можно вызвать откуда угодно, что, кстати, опять приводит к проблемам с incosistent accessibility и тянет распротекчивание параметров. Ну почему в шарпе нет френдов?
Может это плохой дизайн, если можно создавать через фабрику и плохо когда через конструктор? т.е. нормально, где коструктор будет паблик, в остальный случаях можно делать нестед классы
Для решения твоей проблемы можно вот что сделать...
Делаем две сборки.
В одной твой класс и фабрика для него.
Пишем у конструктора класса волшебное слово internal и все получается отлично!
(если че, вторая сборка - это та, которая будет твою фабрику будет юзать. Вторая сборка, она и не одна может быть. Вторых много может быть)
Код далее:
Сборка ClassFactory:
Class.cs:
namespace ClassFactory
{
public class Class
{
private string name;
internal Class(string name)
{
this.name = name;
}
public string Name
{
get { return name; }
set { name = value; }
}
}
}
Factory.cs:
namespace ClassFactory
{
public class Factory
{
private Factory {}
public static Class GenClass
{
return new Class("135");
}
}
}
Сборка User (codename "Вторая"):
Main.cs:
using System;
using ClassFactory;
namespace User
{
class Class1
{
[STAThread]
static void Main(string[] args)
{
Class cl = Factory.GenClass;
//Class cl2 = new Class("10");
Console.WriteLine(cl.Name);
Console.WriteLine("Enter to finish");
Console.ReadLine;
}
}
}
Но мне не нравится Волшебное Слово Интернал! То есть оно мне, конечно, очень нравится, но кажется, что оно не совсем для этого предназначено. Хотя фиг знает, конечно.
И сказал он, что это некоторое подобие ключевого слова friend из плюсов.
Я подумал и подумал, что он, похоже, прав.
Помню, ты горевал, что в шарпе нет друзей. Так вот. Теперь можешь смело перестать!
Слово интернал я, как ты мог заметить, знаю.
Видишь ли, мне не кажется, что открытие доступа к полю для всей ассембли (которая может быть достаточно большой, между прочим) это достойное решение. Контроль за доступом - это же не защита от хакеров, вовсе нет. Это средство для структурирования собственных мыслей.
Модификаторы доступа - для того, чтобы хорошо подумать один раз над проблемой, решить ее и забыть, а компилер будет потом подсказывать, что ты пытаешься сделать то, что делать, как ты уже давно решил, нельзя.
Но другого варианта решения предложенной тобой задачи, похоже, нет.
Я вместе с тобой скорблю о том, что в шарпе нет friend-ов.
Более того, я считаю, что friend - это тоже плохое решение.
Я бы предпочел возможность максимально детального контроля за доступом к каждому члену класса каждого класса.
Но такого, насколько я знаю, нигде нет. А жаль...
ЗЫ. Адинец тебя замочит
Можно заюзать вложенный класс.
Пусть твоя фабрика будет вложена в класс, объект которого ты хочешь породить.
Тогда у нее будет доступ к констуктору твоего класса, пусть даже он будет private.
Ну дальше понятно, я думаю.
Хотя у такого решения есть потенциальные минусы.
1. Есть вероятность, что твоя фабрика сможет порождать только объекты одного класса.
Тогда можно будет сделать суперфабрику, которая будет юзать фабрики, но будет предоставлять интерфейс для работы с несколькими классами.
2. Можно засунуть твою фабрику в родительский класс для объектов, которые она должна порождать. Не берусь сказать, будет ли она иметь доступ к конструкторам дочерних объектов, если они будут не public.
Короче, это все можно проверить, но меня ломает.
Оставить комментарий
bleyman
А Е!Я наконец понял, зачем в мсиле нужен аксесс модифаер FamilyAndAssembly: если у меня есть
internal class A {...}
public class B
{
protected void DoSomething (A a) {...}
...
}
То оно ругается на инконсистент визибилити (и правильно делает). А protected internal соответствует FamilyOrAssembly. Поэтому нужно либо писать только internal (а про протектед писать текстом в комменте либо делать A нестед протектед классом в B, что мб слегка лучше с архитектурной точки зрения, но местами геморней - больше кода писать приходится. Кажется. Не люблю нестед классы =)
А почему в шарпе нет эквивалента FamilyAndAssembly?