Pergunta

Vamos dizer que eu tenho uma interface como:

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

E em ASP.NET MVC Eu tenho um formulário que os postos para a ação do controlador como este:

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

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

Onde SimpleThing é uma classe concreta que mal implementos IThing .

No entanto, eu gostaria que todos os meus métodos para lidar com a interface. Eu tenho um conjunto de dados conjunto que utiliza NHiberate e seu próprio IThing implementação (vamos chamá-lo RealThing ). Eu não posso passar o SimpleThing a ele, porque ele vai reclamar uma "entidade desconhecida".

Alguém tem alguma idéia sobre uma maneira mais limpa de fazer isso? Eu estava pensando em algo ao longo das linhas de usar uma classe de fábrica. Mas como eu ia obter o formulário aglutinante MVC para usá-lo?

Obrigado!

Foi útil?

Solução 3

Houve algumas boas sugestões aqui e eu realmente veio com uma solução que funciona. No entanto, acabei com algo completamente. Acabei de criar modelos específicos para os dados do formulário que eu estava postando e usou o fichário de modelo padrão.

Muito mais simples e isso me permite capturar dados que não faz parte do meu modelo de domínio (ie., Como um campo "Comentários").

Outras dicas

Você pode usar costume ligantes modelo . No entanto artigo no MSDN é totalmente inútil. Então é melhor empregar procurar e encontrar algo melhor. Há planaty de artigos disponíveis.

Eu vim com duas abordagens para isso.

O primeiro foi para adicionar código para minha classe NHibernate Repository para traduzir o tipo simples POCO usado pelo controlador MVC ( SimpleThing ) com o tipo de entidade que NHibernate queria ( 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;
        }            
    }

Assim, qualquer método no repositório pode chamar GetKnownEntity (ponto T) e ele irá copiar as propriedades do item que você passar para o tipo que NHibernate quer. Obviamente, isso sentiu um desajeitado pouco, então eu olhei para pastas modelo personalizado.


Na segunda abordagem, eu criei um fichário de modelo personalizado como este:

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

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

        return new T();                       
    }

}

Então eu registrado que em Global.asax.cs com:

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

E funciona bem com uma ação de controlador que se parece com isso:

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

Eu gosto da segunda abordagem, mas a maioria das minhas coisas injeção de dependência está na classe Controller. Eu não gosto de ter que adicionar todos esses mapeamentos ModelBinder em Global.asax.cs.

Este não é unswer dirrect à sua pergunta.

Nós usamos abordagem ligeiramente diferente para lidar com o mesmo problema que você tem. Nossos controladores aceita DTOs que correspondem campo entidade persistente pelo campo. Então nós utilizador AutoMapper para criar entidades persisten que vão para o banco de dados. Este unnessesery Elimina interfaces e bloqueia público enfrenta API (significa que campo renomeando do objeto persistência não vai quebrar o nosso código de cliente).

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top