Общий шаблон обмена сообщениями в C # - PullRequest
4 голосов
/ 08 сентября 2011

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

public class ArticleService {
     public IResponse AddArticleToCategory(IAddRelatedItemRequest<Category, Article> request) {
     // do stuff with the request
     }
}

Я бы хотел, чтобы интерфейс IAddRelatedItemRequest был универсальным, чтобы его можно было использовать для любого запроса на добавление, например:

public interface IAddRelatedItemRequest<T, U>
where T : class
where U : class {
    Object Key { get;set; }
    List<Object> RelatedKey { get;set; }
}

То, что происходит, заключается в том, что для запроса требуется первичный ключ элемента (например, категория) и список первичных ключей связанных элементов (например, статьи).Класс AddCommentToArticle в конкретном ArticleService затем извлекает элемент по его ключу, а затем добавляет к нему связанные ключевые элементы.

(NB. Чего я не хочу, так это предоставить фактическую сущность и список связанных сущностей - это нужно сделать через примитивные первичные ключи)

Я хочу строго напечататьзапросить каким-либо образом, поэтому вместо поставляемого объекта и списка объектов я могу предоставить (например) Guid и список целых чисел.

Я не особо хочу предоставлять эти два типа через Genericsтак как это делает код менее читаемым, а ключи объектов могут потенциально изменить тип.

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

Ответы [ 2 ]

1 голос
/ 12 сентября 2011

Я не совсем уверен, что полностью следую вашему примеру, но звучит так, будто вы хотите что-то вроде этого:

interface IKeyResolver<T, TKey>
{
  TKey GetKey(T item);
}

public interface IAddRelatedItemRequest<TParentKey, TChildKey>
{
  TParentKey Key { get;set; }
  List<TChildKey> RelatedKey { get;set; }
}

// assume categories have an int key
class CategoryKeyResolver : IKeyResolver<int>
{
  int GetKey(Category c) { return c.CategoryId; }
}

// assume articles use a GUID
class ArticleKeyResolver : IKeyResolver<Guid>
{
  Guid GetKey(Article a) { return a.ArticleId;
}

Затем вы будете использовать соответствующие средства распознавания ключей в своих методах обслуживания. Решающие устройства ключей могут быть свойствами в вашем сервисе или просто создавать соответствующий инструмент для разрешения ключей по мере необходимости. Нечто похожее на средство распознавания ключей действительно полезно, когда ваш основной механизм персистентности сам по себе является общим (например, универсальная реализация репозитория).

0 голосов
/ 12 сентября 2011

Компилятор C # может вывести типы для вас - по крайней мере, в одном месте, где они определены. Во-первых, вы не можете использовать where T : class, потому что int и Guid не являются ссылочными типами. Поэтому определение вашего интерфейса будет выглядеть так:

public interface IAddRelatedItemRequest<T, U>
{
    T Key { get; set; }
    IList<U> RelatedKey { get; set; }
} 

Вы бы тогда это реализовали. Это будет ваша центральная «контрольная точка» для типов клавиш:

public class SomeItemRequest : IAddRelatedItemRequest<int, int>
{
}

Сделайте ваш метод универсальным, и компилятор C # может определить для вас типы:

public static IResponse AddArticleToCategory<T, U>(IAddRelatedItemRequest<T, U> request)
{
    return null;
}
// Usage:
ArticleService.AddArticleToCategory(new SomeItemRequest());

Я считаю, что пример использования - это то, что вам нужно.

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