Question

Disons que j'ai une interface comme:

interface IThing {
   int Id { get; set; }
   string Title { get; set; }
}

Et dans ASP.NET MVC J'ai une forme que les postes à une action de contrôleur comme ceci:

 [AcceptVerbs(HttpVerbs.Post)]
 public ActionResult NewThing([Bind(Exclude = "Id")] SimpleThing thing) {

    // code to validate and persist the thing can go here            
 }

SimpleThing est une classe concrète qui vient à peine outils IThing .

Cependant, je voudrais que tous mes méthodes pour faire face à l'interface. J'ai un ensemble de données qui utilise NHiberate et son IThing mise en œuvre (nous allons l'appeler RealThing ). Je ne peux pas passer le SimpleThing à lui parce qu'il se plaindra d'une « entité inconnue ».

Est-ce que quelqu'un a des idées sur un moyen plus propre de le faire? Je pensais à quelque chose le long des lignes d'aide d'une classe d'usine. Mais comment pourrais-je obtenir le liant sous forme MVC pour l'utiliser?

Merci!

Était-ce utile?

La solution 3

Il y avait quelques bonnes suggestions ici et je fait est venu avec une solution qui fonctionne. Cependant, je me suis retrouvé avec quelque chose de tout à fait. Je viens de créer des modèles spécifiques pour les données de formulaire, je postais et a utilisé le modèle de liaison par défaut.

Beaucoup plus simple et il me permet de capturer des données qui ne fait pas partie de mon modèle de domaine (par exemple. Comme un champ « commentaires »).

Autres conseils

Vous pouvez utiliser personnalisée classeurs modèles . Toutefois, l'article sur msdn est totalement inutile. Il vaudrait donc mieux d'employer la recherche et de trouver quelque chose de mieux. Il y a planaty d'articles disponibles.

Je suis venu avec deux approches à ce sujet.

Le premier était d'ajouter du code à ma classe NHibernate Repository pour traduire le type simple POCO utilisé par le contrôleur MVC ( SimpleThing ) le type d'entité qui NHibernate voulait ( RealThing ):

/// <summary>
/// A NHibernate generic repository.  Provides base of common 
/// methods to retrieve and update data.
/// </summary>
/// <typeparam name="T">The base type to expose 
/// repository methods for.</typeparam>
/// <typeparam name="K">The concrete type used by NHibernate</typeparam>
public class NHRepositoryBase<T, K> 
    : IRepository<T>
    where T : class
    where K : T, new()
{
    // repository methods ...

    /// <summary>
    /// Return T item as a type of K, converting it if necessary
    /// </summary>        
    protected static K GetKnownEntity(T item) {
        if (typeof(T) != typeof(K)) {
            K knownEntity = new K();

            foreach (var prop in typeof(T).GetProperties()) { 
                object value = prop.GetValue(item, null);
                prop.SetValue(knownEntity, value, null);
            }

            return knownEntity;
        } else {

            return (K)item;
        }            
    }

Ainsi, toute méthode dans le référentiel peut appeler GetKnownEntity (T article) et il copiera les propriétés de l'élément que vous passez le type qui veut NHibernate. Évidemment, cela sentait un peu maladroit, alors j'ai regardé pour classeurs modèle personnalisé.


Dans la seconde approche, j'ai créé un liant modèle personnalisé comme ceci:

public class FactoryModelBinder<T> 
    : DefaultModelBinder 
    where T : new() 
{

    protected override object CreateModel(ControllerContext controllerContext, 
                                          ModelBindingContext bindingContext, 
                                          Type modelType) {

        return new T();                       
    }

}

J'ENREGISTRÉ en Global.asax.cs avec:

ModelBinders.Binders.Add(typeof(IThing), 
            new FactoryModelBinder<RealThing>());

Et cela fonctionne très bien avec une action de contrôleur qui ressemble à ceci:

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult NewThing([Bind(Exclude = "Id")] IThing thing) {
    // code to process the thing goes here
}

J'aime la deuxième approche, mais la plupart de mes affaires d'injection de dépendance est dans la classe de contrôleur. Je n'aime pas avoir à ajouter toutes ces applications ModelBinder dans Global.asax.cs.

Ce ne dirrect unswer à votre question.

Nous utilisons l'approche légèrement différente pour traiter même problème que vous avez. Nos contrôleurs accepte DTO qui correspondent à champ d'une entité persistante par champ. Ensuite, nous AutoMapper pour créer des entités persisten qui vont à la base de données. Cela élimine les interfaces unnessesery et verrouille l'API public face (signifie que renommer le champ persistence de l'objet ne brisera pas notre code client).

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top