2010-12-08 4 views
7

Ich muss meinen benutzerdefinierten ModelBinder bis zu meinem DI-Container in MVC 3 verbinden, aber ich kann es nicht funktionieren.Beispiel IModelBinderProvider-Implementierung für ModelBinder-Konstruktorinjektion in MVC 3

So. Dies ist, was ich habe: Ein ModelBinder mit einem Konstruktor injiziert Dienst.

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

Mein Bindemittel funktioniert gut, wenn ich es so hinzufügen:

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

Aber das ist die alte Art und Weise, es zu tun, und ich will das nicht.

Was ich brauche, ist Hilfe, wie dieser Modelbinder bis zu dem IDependencyResolver eingehängt wird, den ich registriert habe.

Laut Brad Wilson verwendet das Geheimnis eine IModelBinderProvider-Implementierung, aber es ist sehr unklar, wie man das verdrahtet. (in this post)

Hat jemand ein Beispiel?

+1

IModelBinderProvider wäre Ihre eigene Implementierung. Es ist nur so passiert, ich schrieb einen Blog-Post über genau diese Sache http://buildstarted.com/2010/12/02/modelbinderproviders-automatic-binding-your-models-is-easy-as-pie/ Hoffe das hilft – Buildstarted

+0

Yeah das funktioniert gut. Ich ersetze einfach den CreateInstance() stuff mit var instance = (IModelBinder) DependencyResolver.Current.GetService (type); Danke! . –

+0

Ich denke immer noch, dass es möglich sein sollte, eine sauberere Implementierung mit Generika zu machen. Ich muss darauf schlafen, denke ich;) –

Antwort

7

ich die gleiche Situation konfrontiert, wenn meine MVC 3 app Codierung. Am Ende hatte ich so etwas wie dieses:

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

Dann habe ich in meinem IoC-Container (in meinem Fall Unity) registriert:

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

Dies funktioniert für mich.

5

Sie benötigen eine eigene IModelBinderProvider und registrieren Sie es mit der ModelBinderProviders.BinderProviders Sammlung schreiben:

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

In Global.asax:

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

Ist es besser, den IModelBinderProvider in IoC zu registrieren, so dass MVC es automatisch anfordert oder es explizit mit BinderProviders.Add (...) registriert? Wenn wir versuchen, mit mehreren Bindemitteln umzugehen (basierend auf dem Modelltyp), gibt es dann ein Muster, das Sie empfehlen würden? – kidoman

+0

Sie könnten es so oder so tun. Ich schätze, ich bevorzuge nur den traditionellen Ansatz. – marcind

+0

Wie versuchen Sie, mit mehreren Ordnern umzugehen? Der erste Binderanbieter, der einen Nicht-Null-Binder zurückgibt, gewinnt. Es geht also nur darum, die Dinge angemessen zu ordnen. – marcind