Как определить «открытый» и «частный» интерфейсы для объекта? - PullRequest
1 голос
/ 04 апреля 2011

У меня есть база данных и класс DAL, который управляет отображением объекта в данные (и наоборот), аналогично Entity Frameworks - но мы пока не можем использовать EF, поэтому DAL довольнопростая доморощенная библиотека, которая выставляет несколько объектов и позволяет выполнять над ними действия.Это работает и будет работать до тех пор, пока мы не перейдем к «правильному» решению EF.

DAL предлагает множество объектов для «клиентских» приложений, с методами и свойствами, определенными для инкапсуляции логики каждого действия искрыть внутреннее состояние этих объектов, а также механизмы, необходимые для сохранения их в базе данных.Это тоже работает.

Однако есть некоторые действия, которые предоставляются объектными интерфейсами DAL, которые действительно должны быть «частными» - они используются приложением-службой, которое выполняется в другом месте, делая различные фоновые вещи дляобъекты в базе данных.Я на самом деле не хочу, чтобы «клиентские» приложения могли видеть эти методы, но я делаю хочу, чтобы методы были видны, когда на приложение DAL ссылается приложение службы.

Примертекущей реализации:

DAL Library
  Object
    Method LoadObject()
    Method SaveObject()
    Method AdjustInternalObjectProperty()

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

Таким образом, вопрос в том, каков наилучший подход, который сохранит намерение использовать интерфейсы для каждого объекта, но который будетскрыть «части этого интерфейса» и сделать скрытые части доступными только для «дружественного» сервисного приложения.Есть ли какой-то метод модификатора доступа, который позволит мне сделать определенные части интерфейса «приватными», с механизмом, который приложение-служба использует (но не клиент) для получения доступа к этим частным элементам?Или это сценарий, в котором должны существовать два разных интерфейса, где интерфейс «клиент» просто пропускает «внутренние» методы?Или что-то еще?

Я хочу сделать это «правильным» способом - я искал SO и нашел кучу ответов на вопросы, касающиеся нескольких объектных интерфейсов, но ни один из них, кажется, не совсем подходит для моего конкретного вопроса.,Если является существующим ответом, непременно укажите мне на него и закройте этот вопрос.

РЕДАКТИРОВАТЬ (после прочтения ответов и экспериментов):

using System;
using System.Runtime.CompilerServices;

[assembly: InternalsVisibleTo("Test")]

namespace Interface_Test
{
  public interface IStandard
  {
    void StandardMethod();
  }
  internal interface ISuper : IStandard
  {
    void SuperMethod();
  }

  public sealed class TestClass : ISuper
  {
    public void StandardMethod()
    {
      Console.WriteLine("The standard method");
    }
    void ISuper.SuperMethod()
    {
      Console.WriteLine("The super method");
    }
  }
}

Это делает свою работу - большая часть экспонирования объекта проходит через интерфейс IStandard, который является стандартным общедоступным интерфейсом, который могут использовать любые клиентские сборки.«Ограниченные» элементы доступны только через альтернативный интерфейс ISuper, который наследует все основные элементы из IStandard, но добавляет дополнительные элементы, которые я хочу использовать только конкретному «клиенту службы».При добавлении атрибута [InternalsVisibleTo], как было предложено, этот интерфейс и его методы / свойства становятся полностью невидимыми для всех, кроме именованной сборки.

Недостатком является то, что есть два интерфейса, но в отсутствие языкавозможность использования 'internal' в качестве модификатора в определениях метода интерфейса - это разумный способ гарантировать, что клиентские сборки не смогут получить доступ к функциям, поддерживаемым интерфейсом, но которые не предназначены для общего использования.

Ответы [ 2 ]

4 голосов
/ 04 апреля 2011

Один из вариантов:

  • Создать internal интерфейс
  • Реализовать его явно (чтобы не требовались публичные методы)
  • Используйте [InternalsVisibleTo], чтобы предоставить вашему «служебному приложению» доступ к внутреннему интерфейсу

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

3 голосов
/ 04 апреля 2011

Один общий подход состоит в том, чтобы иметь 2 интерфейса:

public interface IBar
{
   void DoSimpleStudd();
   int This {get;}

}

public interface ISuperBar : IBar
{
   void DoComplexStuff();
   int That {get; set;}

}

// at service layer
public class ServiceWidget
{
    public ISuperBar Bar {get; set;}
    ...
}

// other places
public class ServiceWidget
{
    public IBar Bar {get; set;}
    ...
}

Так что в service layer они будут использовать ISuperBar, а в других частях приложения они будут использовать IBar.

ОБНОВЛЕНИЕ

Да, интерфейсы должны быть общедоступными.

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