2010-12-08 17 views
7

Necesito conectar mi ModelBinder personalizado a mi contenedor DI en MVC 3, pero no puedo hacerlo funcionar.Ejemplo de implementación IModelBinderProvider para la inyección de constructor ModelBinder en MVC 3

So. Esto es lo que tengo: A ModelBinder con un servicio de constructor inyectado.

public class ProductModelBinder : IModelBinder{ 
    public ProductModelBinder(IProductService productService){/*sets field*/} 
    // the rest don't matter. It works. 
} 

Mi ligante funciona bien si agrego así:

ModelBinders.Binders.Add(typeof(Product), 
    new ProductModelBinder(IoC.Resolve<IProductService>())); 

pero esa es la vieja manera de hacerlo, y no quiero eso.

Lo que necesito es ayuda sobre cómo enganchar ese modelbinder al IDependencyResolver que he registrado.

De acuerdo con Brad Wilson, el secreto está usando una implementación de IModelBinderProvider, pero no está claro cómo conectarlo. (in this post)

¿Alguien tiene un ejemplo?

+1

IModelBinderProvider sería su propia implementación. Da la casualidad de que escribí una publicación en el blog sobre este tema http://buildstarted.com/2010/12/02/modelbinderproviders-automatic-binding-your-models-is-easy-as-pie/ Espero que esto ayude – Buildstarted

+0

Sí , eso está funcionando bien. Simplemente reemplazo el elemento CreateInstance() con var instance = (IModelBinder) DependencyResolver.Current.GetService (type); Gracias! . –

+0

Todavía creo que debería ser posible hacer una implementación más limpia usando genéricos. Necesito dormir sobre eso, creo;) –

Respuesta

7

que enfrentan la misma situación en la codificación de mi aplicación MVC 3. Terminé con algo como esto:

public class ModelBinderProvider : IModelBinderProvider 
{ 
    private static Type IfSubClassOrSame(Type subClass, Type baseClass, Type binder) 
    { 
     if (subClass == baseClass || subClass.IsSubclassOf(baseClass)) 
      return binder; 
     else 
      return null; 
    } 

    public IModelBinder GetBinder(Type modelType) 
    { 
     var binderType = 
      IfSubClassOrSame(modelType, typeof(xCommand), typeof(xCommandBinder)) ?? 
      IfSubClassOrSame(modelType, typeof(yCommand), typeof(yCommandBinder)) ?? null; 

     return binderType != null ? (IModelBinder) IoC.Resolve(binderType) : null; 
    } 
} 

Entonces registró esto en mi contenedor IoC (Unidad en mi caso):

_container.RegisterType<IModelBinderProvider, ModelBinderProvider>("ModelBinderProvider", singleton()); 

Esto funciona para mí.

5

tiene que escribir su propio IModelBinderProvider y registrarlo con la colección ModelBinderProviders.BinderProviders:

public class YourModelBinderProvider : IModelBinderProvider { 
    public IModelBinder GetBinder(Type modelType) { 
     if(modelType == typeof(Product)) { 
      return new ProductModelBinder(...); 
     } 
     return null; 
    } 
} 

En Global.asax:

ModelBinderProviders.BinderProviders.Add(new YourModelBinderProvider()); 
+0

¿Es mejor registrar el IModelBinderProvider en IoC para que MVC lo solicite automáticamente o lo registre explícitamente utilizando BinderProviders.Add (...)? Además, si estamos tratando de manejar varios encuadernadores (según el tipo de modelo), ¿hay algún patrón que recomiende? – kidoman

+0

Puedes hacerlo de cualquier manera. Supongo que prefiero el enfoque tradicional. – marcind

+0

¿Cómo está tratando de manejar múltiples carpetas? El primer proveedor de carpetas que devuelve una carpeta no nula gana. Entonces, solo es cuestión de ordenar las cosas de manera apropiada. – marcind

Cuestiones relacionadas