0

Je suis à la recherche de la manière la plus appropriée de gérer un flux d'activité utilisateur sur mon site de réseau social. En ce moment j'ai plusieurs activités qui peuvent apparaître sur les flux de nouvelles telles que:NHibernate + ASP.Net Flux d'activité utilisateur MVC +

  • utilisateurs rejoint le site
  • Commentaires d'utilisateurs sur un poste
  • utilisateur ajoute un message à leurs favoris
  • utilisateur ajoute un nouveau poste sur le site

Voici une version simplifiée de mon domaine d'objets au 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"; 
    } 
} 

Comme vous pouvez le voir pour le moment j'ai une propriété qui doit être substituée sur chaque activité appelée GetNewsHtml. Ce n'est pas idéal car je ne crois pas que mon domaine devrait être responsable de générer mon code HTML.

J'ai envisagé d'utiliser une vue partielle pour chaque type d'activité et de lui passer la classe de base NewsItem dans le type correct.

Cependant, je suis ouvert aux suggestions.

Répondre

0

J'ai un problème similaire mais avec des types de commande différents. J'ai décidé de définir le rendu à la couche vue (web/controllers), pas au domaine. Vous pouvez le faire de cette façon:

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

Ensuite, vous pouvez transmettre NewsRendererFactory au contrôleur. Il y a peut-être un moyen d'éviter ServiceLocator mais pour le moment je ne peux pas le dire.

Notez que cela rend votre architecture à la fois configurable et connectable si nécessaire. Vous pouvez définir des interfaces supplémentaires liées au rendu, ajouter plus de propriétés à l'IRenderer - par exemple, PartialName, etc, ou avoir des filtres lambda sur IRenderer que Factory utilise pour décider si cette implémentation d'interface est applicable pour le passé (à GetRenderer ("condition")) condition. Beaucoup de choses sont possibles.

Si vous ne voulez pas de conteneurs IoC (ServiceLocator), vous pouvez faire son travail avec une simple instruction switch() dans NewsRendererFactory.GetRenderer. Cela permettra d'isoler la logique à l'intérieur de la méthode d'usine unique, et vous serez en mesure de le remplacer facilement avec le vrai IoC une fois que vous êtes prêt.

Mise à jour: comment obtenir des moteurs de rendu.

Si vous n'utilisez pas IoC, vous faites quelque chose comme

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

Ensuite, vous pouvez sélectionner SingleOrDefault() ou ToList() si vous pouvez gérer plusieurs moteurs de rendu.

+0

merci pour la réponse. Cela ressemble exactement à ce que je dois faire et transmet la responsabilité de mon affichage au niveau du contrôleur. Merci! –

+0

J'essaie de mettre cela en place, mais j'ai du mal à trouver comment appeler GetRenderer lorsque j'ai une liste de différents types de NewsItem (comme un menuisier, mise à jour de statut, etc). Avez-vous une solution pour cela? –

+0

J'ai ajouté une réponse sur comment faire ceci sans IoC. La réponse de l'IoC varie selon les différents conteneurs (Windsor, etc.), donc je ne peux pas en donner un générique. Pour une implémentation manuelle, une simple mise en cache accélérerait la solution. – queen3