【问题标题】:NHibernate + ASP.Net MVC + User Activity FeedNHibernate + ASP.Net MVC + 用户活动源
【发布时间】:2010-02-04 02:09:18
【问题描述】:

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

  • 用户加入网站
  • 帖子中的用户 cmets
  • 用户将帖子添加到收藏夹
  • 用户向网站添加新帖子

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

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

不过我愿意接受建议。

【问题讨论】:

    标签: c# asp.net-mvc nhibernate domain-driven-design user-activity


    【解决方案1】:

    我有类似的问题,但订单类型不同。我决定在视图层(网络/控制器)定义渲染,而不是域。你可以这样做:

    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( “某些条件”))条件。很多事情都是可能的。

    如果您不想要 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()。

    【讨论】:

    • 感谢您的回答。听起来正是我需要做的,并将我的显示器的责任传递给控制器​​级别。谢谢!
    • 我正在尝试启动并运行它,但是当我有不同类型的 NewsItem 的列表(例如加入者、状态更新)时,我正在努力解决如何调用 GetRenderer ETC)。您对此有解决方案吗?
    • 我已经添加了关于如何在没有 IoC 的情况下执行此操作的答案。与 IoC 相关的答案因不同的容器(Windsor 等)而异,所以我不能给出一个通用的答案。对于手动实施,简单的缓存将加快解决方案。
    • 嗨,如果我在这里很愚蠢,请原谅我,但我对泛型还很陌生,你提供的代码似乎只返回 IRenderer 接口而不是每个具体的类,例如 NewsJoinerRenderer:IRenderer。我还假设“requestedTypeArguments”应该是我想要的 NewsItem 的类型......例如 typeof(NewsItemJoiner)?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-01-23
    • 1970-01-01
    • 1970-01-01
    • 2010-12-21
    • 2013-09-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多