Предложения по обеспечению инкапсуляции - PullRequest
2 голосов
/ 22 июля 2011

В моем решении у меня есть проект DLL, скажем Project1, которому принадлежит класс, скажем class A.Этот класс имеет некоторые свойства, настолько важные, что должны быть установлены только в этой DLL.Любые другие проекты, которые ссылаются на эту DLL, могут использовать только геттеры.До сих пор я справлялся с ситуацией, обращаясь к сеттерам внутри, например:

public class A
{
  int Num1 
  {
    get; 
    internal set;
  }

  int Num2 
  {
    get; 
    internal set;
  }
} 

Сейчас мне нужно добавить еще один проект, Project2, к решению, которое не только должно использовать class A (обаgetters и setter) но также, Project1 имеет ссылку на этот новый проект.Поэтому я решил отделить class A в другом определении dll, на вершине иерархии.В этом и заключается моя проблема.Теперь все сеттеры невидимы для Project1 и Project2.Если я удалю аксессор internal, тогда сеттеры будут доступны для любой сборки, которая ссылается на определение dll.Я не хочу этого, потому что информация о class A так важна, что ее нельзя устанавливать по ошибке.

Как я могу ограничить доступ к сеттерам class A извне Project1 иProject2?

Мне приходит в голову только решение использовать InternalsVisibleTo.Я не знаю, это не звучит идеально.Кроме того, объединение Project1 и Project2 было бы еще одним решением, но эти два отвечают за совершенно разные задачи, это не лучший вариант для разработки.

Ответы [ 3 ]

2 голосов
/ 22 июля 2011

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

[assembly: InternalsVisibleTo("AssemblyName")]

Вы можете сделать это на уровне класса или во всей сборке, если хотите.

InternalsVisibleToAttribute Class

0 голосов
/ 22 июля 2011

Если я прав, предполагая, что Project1 выполняет какую-то конкретную работу, а Project2 является абстракцией, то это кандидат на инверсию управления - в идеале, реализациядолжен зависеть от абстракции , а не наоборот.

Если вещи в Project2 должны управлять чем-то, что определено в Project1, создать интерфейс в Project2 и заставить Project2 взаимодействовать с интерфейсом, затем реализовать интерфейсв Project1 и делайте всю грязную работу внутренне.

0 голосов
/ 22 июля 2011

вы всегда можете сделать что-то вроде этого (кошмар дизайна, но делает то, что вы просили):

public class A
{
  int _Num1, _Num2;

  int Num1 {get {return _Num1;}; }
  int Num2 {get {return _Nun2;}; }

  protected void SetNum (int pWhich, int pV)
  {
      if ( pWhich == 1 ) {_Num1 = pV; return;}
      _Num2 = pV;
  } 
} 

и тогда вы можете создать экземпляр класса в обычном порядке ... когда вам нужно установитьЗначения, которые вы используете отражение:

myClassA.GetType().GetMethod ("SetNum", BindingFlags.NonPublic ).Invoke (myClassA, new object[] {1, 777 });
...