0

Я ищу наиболее подходящий способ работы с фидом пользовательских действий на моем сайте социальной сети. На данный момент у меня есть несколько видов деятельности, которые могут появиться на ленте новостей, таких как:NHibernate + ASP.Net MVC + Активность пользователя

  • Пользователи присоединяется к сайту
  • Комментарии пользователей на пост
  • Пользователь добавляет сообщение в своих любимцев добавляет
  • Пользователь новый пост на сайте

Вот упрощенная версия моего домена объекты на данный момент:

public abstract class NewsItem : Entity, ITenantSpecific 
{ 

    public virtual Account Account { get; set; } 
    public virtual DateTime DateTime { get; set; } 

    // returns formatted news html string which gets 
    // overridden by inherted classes 
    public abstract string GetNewsHtml(); 
} 


public class NewsItemJoiner : NewsItem 
{ 
    public virtual Account AccountJoined { get; set; } 

    public override string GetNewsHtml() 
    { 
     return "XXX has just joined our music network"; 
    } 
} 

Как вы можете видеть, на данный момент у меня есть свойство, которое должно быть переопределено при каждом действии, которое называется GetNewsHtml. Это не идеально, поскольку я не считаю, что мой домен должен отвечать за создание моего HTML.

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

Однако я открыт для предложений.

ответ

0

У меня есть аналогичная проблема, но с разными типами заказов. Я решил определить рендеринг на уровне представления (веб/контроллеры), а не на домене. Вы можете сделать это следующим образом:

public interface IRenderer<T> where T: NewsItem 
{ 
    string Render(T item); 
} 

public class NewsItemJoinerRenderer: IRenderer<NewsItemJoiner> 
{ 
    public string Render(T item) 
    { 
     return "XXX has just joined our music network"; 
    } 
} 

public class NewsRendererFactory 
{ 
    public IRenderer<T> GetRenderer<T>() 
    { 
     return ServiceLocator.GetInstance<IRenderer<T>>(); 
    } 
} 

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

Обратите внимание, что при необходимости ваша архитектура может быть конфигурируемой и подключаемой.

Вы можете определить дополнительные интерфейсы, связанные с визуализацией, добавить дополнительные свойства в IRenderer - например, PartialName и т. Д. Или использовать лямбда-фильтры на IRenderer, которые Factory использует для решения, применима ли эта реализация интерфейса для переданного (в GetRenderer (условие «некоторое условие»)). Многое возможно.

Если вы не хотите контейнеры IoC (ServiceLocator), вы можете выполнить свою работу с помощью простого оператора switch() внутри NewsRendererFactory.GetRenderer. Это изолирует логику внутри одного заводского метода, и вы сможете легко заменить ее истинным IoC после того, как будете готовы.

Обновление: как получить рендер.

Если вы не используете IoC, вы делаете что-то вроде

typeof(IRenderer<>).Assembly.GetTypes().Where(x => 
     x.IsGenericType && 
     x.GetGenericTypeDefinition() == typeof(IRenderer<>) && 
     x.GetGenericArguments().FirstOrDefault() == requestedTypeArguments) 

Затем вы можете выбрать SingleOrDefault() или ToList(), если вы можете обрабатывать несколько рендеров.

+0

спасибо за ответ. Похоже, именно то, что мне нужно сделать, и передает ответственность моего дисплея на уровень контроллера. Спасибо! –

+0

Я пытаюсь запустить все это, однако я борюсь с разработкой, как вызвать GetRenderer , когда у меня есть список различных типов NewsItem (например, столяр, обновление статуса и т. Д.). У вас есть решение для этого? –

+0

Я добавил ответ о том, как это сделать без IoC. Ответ на IoC зависит от разных контейнеров (Windsor и т. Д.), Поэтому я не могу дать общий. Для ручной реализации простое кэширование ускорит решение. – queen3

Смежные вопросы