• nopcommerce笔记2


    有时我们需要故意用错误来求得真相。

    有一个控制器如下:

    public class HomeController : Controller
    {
    //
    // GET: /Home/

    public HomeController(int i)
    {
    }

    public ActionResult Index()
    {
    return View();
    }

    }

    屏蔽了无参数的构造函数,在Application_Start中同时屏蔽NopDependencyResolver:

    protected void Application_Start()
    {
    EngineContext.Initialize(false);
    //set dependency resolver
    var dependencyResolver = new NopDependencyResolver();
    //DependencyResolver.SetResolver(dependencyResolver);

    AreaRegistration.RegisterAllAreas();

    WebApiConfig.Register(GlobalConfiguration.Configuration);
    FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
    RouteConfig.RegisterRoutes(RouteTable.Routes);
    }

    访问这个action,错误是:

     放开NopDependencyResolver,错误是:

    可以看到屏蔽NopDependencyResolver时,交给

    System.Activator.CreateInstance
    去创建控制器实例

    放开时,交给

    Nop.Web.Framework.Mvc.NopDependencyResolver.GetService
    去创建控制器实例

    通过对错误提示的分析,放开NopDependencyResolver时,纠结在参数不能解析,于是想到给控制器构造函数参数给默认值,果然就通过了,不再有错误。

    public class HomeController : Controller
    {
    //
    // GET: /Home/

    public HomeController(int i=1)
    {
    }

    public ActionResult Index()
    {
    return View();
    }

    }

    切换成屏蔽NopDependencyResolver时,错误依然。

    然后,还有然后,在网上,根据这个网址:

    http://www.nopchina.com/forum.php?mod=viewthread&tid=109

    又思考了一下,既然是ioc,那么去掉默认值,把int的实例注册进去应该是可以的,也就是这样:

    去掉默认值:

    public class HomeController : Controller
    {
    //
    // GET: /Home/

    public HomeController(int i)
    {
    }

    public ActionResult Index()
    {
    return View();
    }

    }

    注册一个int 单例:

    public class MvcApplication : System.Web.HttpApplication
    {
    protected void Application_Start()
    {
    EngineContext.Initialize(false);
    //set dependency resolver
    var dependencyResolver = new NopDependencyResolver();
    DependencyResolver.SetResolver(dependencyResolver);

    AreaRegistration.RegisterAllAreas();

    WebApiConfig.Register(GlobalConfiguration.Configuration);
    FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
    RouteConfig.RegisterRoutes(RouteTable.Routes);

    EngineContext.Current.ContainerManager.AddComponentInstance<int>(100, "forhome", Nop.Core.Infrastructure.DependencyManagement.ComponentLifeStyle.Singleton);
    }
    }

    结果是没有错误。

    同时好像发现对int这种注册,必须是ComponentLifeStyle.Singleton,改成ComponentLifeStyle.Transient报错如下:

    可以看见很多流程性的东西,至于100为什么必须是单例,也许可以纠结下去,但我还是打住。上面的图贴出来,就是为了看看调用Application_Start的流程而已。

    然后想到,我注册多个int,效果是怎样的?

    于是:

    控制器:

    public class HomeController : Controller
    {
    //
    // GET: /Home/
    private int n;

    public HomeController(int i)
    {
    n = i;
    }

    public ActionResult Index()
    {
    ViewBag.n = n;
    return View();
    }

    }

    view:

    @{
    ViewBag.Title = "Index";
    }

    <h2>@ViewBag.n</h2>

     Application_Start:

    protected void Application_Start()
    {
    EngineContext.Initialize(false);
    //set dependency resolver
    var dependencyResolver = new NopDependencyResolver();
    DependencyResolver.SetResolver(dependencyResolver);

    AreaRegistration.RegisterAllAreas();

    WebApiConfig.Register(GlobalConfiguration.Configuration);
    FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
    RouteConfig.RegisterRoutes(RouteTable.Routes);

    EngineContext.Current.ContainerManager.AddComponentInstance<int>(100, "forhome1", Nop.Core.Infrastructure.DependencyManagement.ComponentLifeStyle.Singleton);


    EngineContext.Current.ContainerManager.AddComponentInstance<int>(999, "forhome2", Nop.Core.Infrastructure.DependencyManagement.ComponentLifeStyle.Singleton);


    EngineContext.Current.ContainerManager.AddComponentInstance<int>(777, "forhome3", Nop.Core.Infrastructure.DependencyManagement.ComponentLifeStyle.Singleton);
    }

    我猜是777,结果是它。

    然后,又想到是否可以在:

    protected void Application_BeginRequest(object sender, EventArgs e)
    {
    EngineContext.Current.ContainerManager.AddComponentInstance<HomeController>(new HomeController(2000), "ddd", Nop.Core.Infrastructure.DependencyManagement.ComponentLifeStyle.Singleton);
    }

    果然是2000,只是和上面一样,为什么必须ComponentLifeStyle.Singleton。

    不是话:

    为什么必须是单例?

    回家后又仔细思考,首先我想清楚了为什么必须是ComponentLifeStyle.Singleton。因为AddComponentInstance注册进ioc容器中的本身就是一个实例,不是容器创建出来的,这样的实例,容器是不应该(不是不能)管理它的生命周期的。

    想要一个临时的实例,应该使用注册基类(或接口)和实现类的方法,这样容器依据实现类创建的实例才可以指定为单例或者临时,这种创建出的实例显然只有通过容器才能拿到,因此它的生命周期完全由容器控制是合理的。

    例子如下:

    protected void Application_BeginRequest(object sender, EventArgs e)
    {
    EngineContext.Current.ContainerManager.AddComponentInstance<int>(2400, "p1");
    Dictionary<string,string> p = new Dictionary<string,string>();
    p.Add("i", "p1");// i是HomeController构造函数参数名

    EngineContext.Current.ContainerManager.AddComponentWithParameters<Controller, HomeController>(p, "kkk", ComponentLifeStyle.Transient);

    }

    结果是2400。

    protected void Application_BeginRequest(object sender, EventArgs e)
    {
    EngineContext.Current.ContainerManager.AddComponentInstance<int>(2500, "p1");

    EngineContext.Current.ContainerManager.AddComponent<Controller, HomeController>( "kkk", ComponentLifeStyle.Transient);

    }

    是2500。

    其实下面一句是多余的,改成如下也是可以的:

    protected void Application_BeginRequest(object sender, EventArgs e)
    {

    EngineContext.Current.ContainerManager.AddComponentInstance<int>(2500, "p1");

    }

    还有一个很重要的发现:

    NopDependencyResolver 与

    PresentationNop.Web.FrameworkDependencyRegistrar.cs

    中的这个注册是息息相关的:

    //controllers
    builder.RegisterControllers(typeFinder.GetAssemblies().ToArray());

    如果不注册,会使用默认方式生成控制器

    我写这么多,觉得收获主要有:

    1、DependencyResolver.SetResolver :让我们有了干涉Controller实例生成的钩子,还可干涉别的啥,暂时不知道

    2、NopDependencyResolver :让我们可以在Autofac的ioc容器中去发挥对Controller的生成控制

    3、进一步理解了ioc

  • 相关阅读:
    ppt中调整图片位置
    如何理解 Google Protocol Buffer
    g++: error: unrecognized command line option ‘-std=C++11’
    手把手教你如何加入到github的开源世界!
    redis
    maven
    Spring----注释----开启Annotation <context:annotation-config> 和 <context:component-scan>诠释及区别
    JMX学习笔记(一)-MBean
    Redis学习笔记2-redis管道(pipeline)
    Redis学习笔记1-java 使用Redis(jedis)
  • 原文地址:https://www.cnblogs.com/whwqs/p/3412622.html
Copyright © 2020-2023  润新知