0

我正在寻找最合适的方式来处理我的社交网站上的用户活动提要。目前,我有几项活动可以出现在新闻提要中,例如:

  • 用户加入网站
  • 用户对帖子的评论
  • 用户将帖子添加到他们的收藏夹
  • 用户向网站添加新帖子

这是目前我的域对象的简化版本:

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基类向下转换为正确的类型。

但是我愿意接受建议。

4

1 回答 1

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 上具有 lambda 过滤器,Factory 使用该过滤器来决定此接口实现是否适用于传递的(到 GetRenderer("some-条件")) 条件。很多事情都是可能的。

如果您不想要 IoC 容器 (ServiceLocator),您可以使用 NewsRendererFactory.GetRenderer 中的简单 switch() 语句来完成它的工作。这将隔离单个工厂方法中的逻辑,一旦准备好,您就可以用真正的 IoC 轻松替换它。

更新:如何获取渲染器。

如果你不使用 IoC,你可以做类似的事情

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

然后,如果您可以处理多个渲染器,则可以选择 SingleOrDefault() 或 ToList()。

于 2010-02-08T20:43:21.453 回答