问题
I'm not sure if my expectations are wrong. I am using ASP.NET MVC (not core) and Autofac. I have an image that appears on every page of my website, and I have created a service to return a random image name like so
INTERFACE
public interface IBreadCrumbImage
{
string GetImage();
}
CLASS (snipped for brevity)
public class BreadCrumbImage : IBreadCrumbImage
{
public string GetImage()
{
return ImageUrl;
}
}
GLOBAL.ASAX.CS (Autofac registration)
protected void Application_Start()
{
var builder = new ContainerBuilder();
builder.RegisterControllers(typeof(MvcApplication).Assembly);
builder.RegisterType<BreadCrumbImage>().As<IBreadCrumbImage>().SingleInstance();
var container = builder.Build();
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
}
CONTROLLER
public class HomeController : Controller
{
private IBreadCrumbImage _breadCrumbImage;
public ActionResult Index(BreadCrumbImage breadCrumbImage)
{
_breadCrumbImage = breadCrumbImage;
var x = _breadCrumbImage.GetImage();
ViewBag.BreadCrumbImage = "/img/BreadCrumbs/" + x;
return View();
}
}
All of this works, and I get my IMAGE showing up random.. however, setting breakpoints, this BreadCrumbImage service is being instantiated every time it is accessed. I'd like to have this instantiated once (the loading of the images is done in the constructor of BreadCrumbImage, it reads files and puts them into an array -- no need to do that more than once on app startup, and the GetImages just grabs rnd from array).
Am I registering this wrong with the SingleInstance, or does this just not work as I'm expecting it to and I'm going to have to have some base resolver that's tied to the builder that's created in Global.asax.cs?
UPDATE: Answer, thank you Travis. Needed to put this in to the autofac configuration, and everything worked like a charm.
builder.RegisterType<ExtensibleActionInvoker>()
.As<IActionInvoker>()
.WithParameter("injectActionMethodParameters", true);
回答1:
Looking at the controller you provided, you're not using constructor injection. The Index
method is an action method, not a constructor. Further, it's asking for a BreadCrumbImage
not an IBreadCrumbImage
.
If you look at the call stack from your breakpoints, I'm guessing you're going to see MVC model binding going on instantiating that BreadCrumbImage
, not Autofac. I don't see anywhere in your Autofac setup that you're using the action parameter injection mechanism, and if you were you'd still see MVC model binding in the call stack because you didn't register BreadCrumbImage
as itself - you registered it as IBreadCrumbImage
so that's the only thing Autofac will resolve it as. You won't be able to resolve the concrete BreadCrumbImage
out of the container using the registrations you're showing.
来源:https://stackoverflow.com/questions/40329725/asp-net-autofac-singleton-running-twice-constructor-injection