внутренние конструкторы в библиотеке C # - PullRequest
1 голос
/ 09 января 2009

Я пишу библиотеку доступа к данным на C #, структура классов моей модели данных выглядит следующим образом (в сборке DataAccess):

public abstract class DataModel {...} (protected constructor)
public abstract class DataClass {...} (protected constructor)
public abstract class DataField {...} (protected constructor)
public class IntegerField : DataField
{
   public IntegerField(DataClass cls, string name, bool isNullable, 
                       int? defaultValue, int? minValue, int? maxValue) {...}
}
public class StringField : DataField
{
   public StringField(DataClass cls, string name, bool isNullable, 
                      string defaultValue, int maxLength) {...}
}
public class BooleanField : DataField
{
   public BooleanField(DataClass cls, string name, bool isNullable, 
                       bool? defaultValue) {...}
}
...

Как видите, у каждого поля свой конструктор.

Чтобы использовать это, вы автоматически генерируете классы из файла XML, например, модель данных «Store», которая содержит класс данных «Customer» и класс данных «Employee», сгенерирует этот код:

public class StoreDataModel : DataModel
{
   public CustomerDataClass Customer { get; private set;}
   public EmployeeDataClass Employee { get; private set;}
   public StoreDataModel()
   {
     Customer = new CustomerDataClass(this);
     AddClass(customer)
     Employee = new EmployeeDataClass(this);
     AddClass(employee)
   }
}
public class CustomerDataClass : DataClass
{
   public StringField FirstNameField { get; private set; }
   public StringField LastNameField { get; private set; }
   public DateField BirthDateField { get; private set; }

   public CustomerDataClass(StoreDataModel model) : base(model)
   {
      FirstNameField = new StringField(this, "FirstName", true, null, 50);
      LastNameField = new StringField(this, "LastName", true, null, 50);
      ...
   }
}
public class EmployeeDataClass : DataClass {...}

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

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

Единственный способ, о котором я мог подумать, - это добавить метод «Initialize» к каждому классу поля, который бы включал свойства этих конкретных полей, и в конструкторе пользовательского класса данных сделать это:

   public CustomerDataClass(StoreDataModel model) : base(model)
   {
      FirstNameField = AddField<StringField>(this, "FirstName", true, null)
                              .Initialize(50);
      LastNameField = AddField<StringField>(this, "LastName", true, null)
                              .Initialize(50);
      ...
   }

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

У кого-нибудь есть лучшее решение?

1 Ответ

3 голосов
/ 09 января 2009

Ну, три варианта:

  • Используйте InternalsVisibleTo, чтобы сделать видимыми конструкторы
  • Создание статических методов в StringField и т. Д. Для создания экземпляров
  • Запись защищенных методов в DataModel или DataClass для создания экземпляров полей (чтобы CustomerDataClass мог вызывать DataClass.CreateStringField и т. Д.)

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

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