NHibernate + ASP.Net MVC +用户活动源

发布于 2024-08-20 08:35:15 字数 896 浏览 10 评论 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 基类向下转换为正确的类型。

不过,我愿意接受建议。

I am looking for the most appropriate way of dealing with a user activity feed on my social networking site. At the moment i have several activities which can appear on the news feed such as:

  • Users joins the site
  • User comments on a post
  • User adds a post to their favorites
  • User adds a new post to the site

Here is a simplified version of my domain objects at the moment:

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";
    }
}

As you can see at the moment I have a property which must be overridden on each activity called GetNewsHtml. This isn't ideal as I don't believe my domain should be responsible for generating my HTML.

I have thought about using a partial view for each activity type and pass into it the NewsItem base class downcasted into the correct type.

However I am open to suggestions.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

娇柔作态 2024-08-27 08:35:15

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

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()。

I have a similar issue but with different order types. I decided to define rendering at the view layer (web/controllers), not domain. You can do it this way:

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>>();
   }
}

Then you can pass NewsRendererFactory to controller. Perhaps there's a way to avoid ServiceLocator but for now I cannot tell.

Notice that this makes your architecture both configurable and pluggable if needed.

You can define additional render-related interfaces, add more properties to the IRenderer - for example, PartialName, etc, or have lambda filters on IRenderer that Factory uses to decide if this interface implementation is applicable for the passed (to GetRenderer("some-condition")) condition. A lot of things are possible.

If you don't want IoC containers (ServiceLocator), you can have its job done with simple switch() statement inside NewsRendererFactory.GetRenderer. This will isolate the logic inside single factory method, and you'll be able to replace it easily with true IoC once you are ready.

Update: how to get renderers.

If you don't use IoC, you do something like

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

Then you can select SingleOrDefault() or ToList() if you can handle multiple renderers.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文