问题
I have the following setup
public interface IObject
{
string Name { get; set;}
}
public class ConcreteObject : IObject
{
public string Name { get; set; }
}
public ActionResult Index(IObject myObject)
{
return View();
}
I have a concrete class which implements IObject, and I am using dependency injection to bind this concrete class to the interface.
Using Autofac, I have the following setup also
var builder = new ContainerBuilder();
builder.RegisterModule(new AutofacWebTypesModule());
builder.RegisterSource(new ViewRegistrationSource());
builder.RegisterFilterProvider();
builder.RegisterControllers(Assembly.GetExecutingAssembly()).InjectActionInvoker().PropertiesAutowired();
builder.RegisterModelBinders(Assembly.GetExecutingAssembly());
builder.RegisterModelBinderProvider();
builder.RegisterType<ExtensibleActionInvoker>().As<IActionInvoker>().WithParameter("injectActionMethodParameters", true);
builder.RegisterType<ConcreteObject>().As<IObject>().InstancePerHttpRequest();
var container = builder.Build();
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
When I run this, I get an instance of the concrete class, but any paramaters that would usually be bound from the querystring are now null. ie: Home/Index?Name=test would bind an instance, but not bind the parameter Name. Is there a way to ensure that modelbinding still happens after DI?
回答1:
Edit: I do no recommend ever doing this, you should never inject interfaces into action methods!.
Ok, I have this solved. I set up a custom model binder which I call when an interface is present.
public class YourModelBinderProvider : IModelBinderProvider
{
public IModelBinder GetBinder(Type modelType)
{
if (modelType.IsInterface)
{
return new InterfaceModelBinder();
}
return null;
}
}
public class InterfaceModelBinder : DefaultModelBinder
{
public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
ModelBindingContext context = new ModelBindingContext(bindingContext);
var item = DependencyResolver.Current.GetService(bindingContext.ModelType);
Func<object> modelAccessor = () => item;
context.ModelMetadata = new ModelMetadata(new DataAnnotationsModelMetadataProvider(),
bindingContext.ModelMetadata.ContainerType, modelAccessor, item.GetType(), bindingContext.ModelName);
return base.BindModel(controllerContext, context);
}
}
Then in my global.asax I simply have
ModelBinderProviders.BinderProviders.Add(new YourModelBinderProvider());
var builder = new ContainerBuilder();
builder.RegisterModelBinderProvider();
builder.RegisterType<ConcreteObject>().As<IObject>();
var container = builder.Build();
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
回答2:
Despite that I don't understand what do you want to achieve using method injection, you can try to invoke TryUpdateModel
method.
来源:https://stackoverflow.com/questions/7859482/autofac-dependency-injection-on-action-method-parameters-asp-mvc3