开发者

NHibernate + ASP.Net MVC + User Activity Feed

开发者 https://www.devze.com 2022-12-19 16:30 出处:网络
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:

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 
   开发者_C百科 // 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.


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.

0

精彩评论

暂无评论...
验证码 换一张
取 消