Дизайн интерфейса с использованием C # Generics - PullRequest
2 голосов
/ 13 мая 2009

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

У меня есть интерфейс IGraphData, который я хотел бы кэшировать с помощью службы, которая обращается к кешу, это называется IGraphDataCacheService и имеет методы set и get для добавления и извлечения объектов IGraphData в кеш и из него. служба кэширования будет одноэлементной.

Я не совсем понимаю, как правильно реализовать это, так что существует только одна служба кэширования, которая может получать и устанавливать общие объекты IgraphData.

Я придумал это:

interface IGraphDataCacheService {

IGraphData<object> Get(string identifier);
void Set(IGraphData<object> graphData);}

или это:

T Get<T, P>(string identifier) where T : IGraphData<P>;
void Set<T,P>(T graphData) where T : IGraphData<P>;

Может ли кто-нибудь предложить какой-нибудь совет помощи?

Спасибо

Ответы [ 5 ]

8 голосов
/ 13 мая 2009

Почему бы вам просто не сделать интерфейс универсальным?

interface ICacheService<T> {
    T Get(string identifier);
    void Set(T graphData);
}

если вы хотите, вы можете задать ограничение типа T для типа IGraphData или записать его как:

interface IGraphDataCacheService<T> {
    IGraphData<T> Get(string identifier);
    void Set(IGraphData<T> graphData);
}
3 голосов
/ 13 мая 2009

Несколько баллов:

  1. Я бы, вероятно, переименовал методы интерфейса, чтобы они стали более символичными для службы кэширования. Например, Fetch и Store вместо Get и Set, что говорит о том, что вы получаете или настраиваете провайдера, а не данные для кэширования.

  2. Обеспечение наличия только одного кэша - это деталь реализации, а не интерфейс.

Чтобы реализовать синглтон, попробуйте что-то вроде:

public class SingletonCacheService : IGraphDataCacheService {
   private static Singleton instance;

   private Singleton() {}

   // snip implementation of IGraphDataCacheService methods ...

   public static Singleton Instance {
      get {
         if (instance == null) {
            instance = new Singleton();
         }
         return instance;
      }
   }
}

Обратите внимание, что эта простая версия не безопасна для потоков.

1 голос
/ 13 мая 2009

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

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

Если вы управляете интерфейсом IGraphData, вы можете создать интерфейс IGraphData, извлечь из него IGraphData и использовать IGraphData для доступа к кешу. Это зависит только от того, как вы его используете и над чем вы управляете.

Вы можете делать то, что вы хотите в C # 4.0. Об этом есть статья здесь

1 голос
/ 13 мая 2009

Обе альтернативы кажутся правдоподобными с первого взгляда; Я догадываюсь, что вам нужно написать «типичный» клиентский код, чтобы принять решение. например Знает ли типичный клиент тип данных, связанных с идентификатором, который он ищет? Хороший дизайн API требует определения основных сценариев использования и использования его для информирования проекта.

0 голосов
/ 13 мая 2009

Вы не можете гарантировать, что есть только один экземпляр, реализующий интерфейс. Однако вы можете сделать класс (например, GraphDataCacheServiceImpl) , реализующий интерфейс , синглтоном, запечатав его и предоставив только свойство getter, при этом объект будет создан как статическая переменная из частного конструктора. Смотрите ниже. Что касается дженериков, не совсем понятно, чего вы хотите достичь. Но я бы предположил, что приведенное ниже близко к тому, что вы хотите.

interface IGraphDataCacheService<T> {

IGraphData<T> Get(string identifier);
void Set(IGraphData<T> graphData);

}


public sealed class GraphDataCacheServiceImpl<T> : IGraphDataCacheService<T>
{

  private GraphDataCacheServiceImpl()
  {
      // ..
  }

  static GraphDataCacheServiceImpl()
  {
    Instance = new GraphDataCacheServiceImpl<T>();
  }

  public IGraphData<T> Get(string id)
  {
      return new GraphDataImpl<T>();
  }

  public void Set(IGraphData<T> graphData)
  {
  }

  public static GraphDataCacheServiceImpl<T> Instance {get; private set;}
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...