Unity 2.0 Web.config 设置与 MVC

发布于 2024-09-27 10:56:02 字数 3425 浏览 3 评论 0原文

我正在尝试将 Unity 2.0 用于我当前的 MVC 项目,但在 web.config 文件中配置参数注入时遇到问题。

这是我所拥有的:

1)家庭控制器:

public class HomeController : Controller
{
    IRepository repository = null;

    public HomeController()
    {
       // Always calls this constructor. Why? 
       // Should be calling the constructor below that takes IRepository.
    }

    public HomeController(IRepository repository)
    {
        // Should be calling this constructor!!!
        this.repository = repository;
    }
    public ActionResult Index()
    {
        List<int> intList = this.repository.GetInts();

        ViewData["Message"] = "Welcome to ASP.NET MVC!";

        return View();
    }

具有两个构造函数的基本控制器。第一个不带任何参数,第二个将 IRepository 作为参数(应该由 Unity 注入)

2) SQL Repository

public class SQLRepository : IRepository
{
    private string connectionString = null;

    public SQLRepository(string connectionString)
    {
        this.connectionString = connectionString;
    }

    #region IRepository Members

    public List<int> GetInts()
    {
        return new List<int>() { 1, 2, 3, 4, 5 };
    }

    #endregion
}

未来将成为 SQL 存储库,但目前它仅实现 1 IRepository 接口的成员,即 GetInts() 并返回整数列表。

3) IRepository Interace

public interface IRepository
{
    List<int> GetInts();
}

接口。

4) Global.asax 文件中的 Application_Start() 事件。

    protected void Application_Start()
    {
        AreaRegistration.RegisterAllAreas();

        RegisterRoutes(RouteTable.Routes);

        IUnityContainer container = new UnityContainer();

        UnityConfigurationSection section = ConfigurationManager.GetSection("unity") as UnityConfigurationSection;
        section.Configure(container, "Default");
    }

这用于从 web.config 文件中读取 Unity 2.0 配置,以便注册和映射类型等。

6) web.config 中的 Unity 2.0 配置部分

<unity>
<typeAliases>
  <typeAlias alias="string" type="System.String, mscorlib" />
  <typeAlias alias="singleton" type="Microsoft.Practices.Unity.ContainerControlledLifetimeManager, Microsoft.Practices.Unity" />
  <typeAlias alias="IRepository" type="NewMVCApp.Interfaces.IRepository, NewMVCApp" />
  <typeAlias alias="SQLRepository" type="NewMVCApp.Repository.SQLRepository, NewMVCApp" />
</typeAliases>
<containers>
  <container name="Default">
    <types>
      <type type="IRepository" mapTo="SQLRepository">
        <lifetime type="singleton" />
        <constructor>
          <param name="connectionString">
            <value value="ApplicationServices" />
          </param>
        </constructor>
      </type>
    </types>
  </container>
</containers>

这是我使用的 Unity 2.0 配置部分。正如您所看到的,它为我的 IRepository 和 SQLRepository 类键入了别名,然后将 IRepository 映射到 SQLRepository。因此,每当请求 IRepository 时,都会提供 SQLRepository 实例。另外,我想通过构造函数将连接字符串传递到我的 SQLRepository。

5) 那么,我想做什么?

我尝试使用 Unity 2.0 将 IRepository (SQLRepository) 实例传递到我的 HomeController。但由于某种原因, HomeController() 的默认无参数构造函数被调用。但 HomeController(IRepository 存储库) 永远不会被调用。我很确定我没有在 web.config 文件中正确设置。但我不确定如何正确设置以便调用 HomeController 上的正确构造函数。请帮忙:)

&谢谢:)

I am trying to use Unity 2.0 for my current project with MVC and having trouble configuring paramter injection in the web.config file.

Here's what I have:

1) A Home Controller:

public class HomeController : Controller
{
    IRepository repository = null;

    public HomeController()
    {
       // Always calls this constructor. Why? 
       // Should be calling the constructor below that takes IRepository.
    }

    public HomeController(IRepository repository)
    {
        // Should be calling this constructor!!!
        this.repository = repository;
    }
    public ActionResult Index()
    {
        List<int> intList = this.repository.GetInts();

        ViewData["Message"] = "Welcome to ASP.NET MVC!";

        return View();
    }

A basic controller with two constructors. The 1st one takes no arguments, and the 2nd one takes IRepository as an argument (that's supposed to be injected by Unity)

2) SQL Repository

public class SQLRepository : IRepository
{
    private string connectionString = null;

    public SQLRepository(string connectionString)
    {
        this.connectionString = connectionString;
    }

    #region IRepository Members

    public List<int> GetInts()
    {
        return new List<int>() { 1, 2, 3, 4, 5 };
    }

    #endregion
}

A future to be SQL repository, but for now it just implements 1 member of the IRepository interface, namely GetInts() and returns a list of integers.

3) IRepository Interace

public interface IRepository
{
    List<int> GetInts();
}

An interface.

4) Application_Start() Event in my Global.asax file.

    protected void Application_Start()
    {
        AreaRegistration.RegisterAllAreas();

        RegisterRoutes(RouteTable.Routes);

        IUnityContainer container = new UnityContainer();

        UnityConfigurationSection section = ConfigurationManager.GetSection("unity") as UnityConfigurationSection;
        section.Configure(container, "Default");
    }

This is used to read the Unity 2.0 configuration from the web.config file in order to register and map types etc.

6) The Unity 2.0 Configuration Section in web.config

<unity>
<typeAliases>
  <typeAlias alias="string" type="System.String, mscorlib" />
  <typeAlias alias="singleton" type="Microsoft.Practices.Unity.ContainerControlledLifetimeManager, Microsoft.Practices.Unity" />
  <typeAlias alias="IRepository" type="NewMVCApp.Interfaces.IRepository, NewMVCApp" />
  <typeAlias alias="SQLRepository" type="NewMVCApp.Repository.SQLRepository, NewMVCApp" />
</typeAliases>
<containers>
  <container name="Default">
    <types>
      <type type="IRepository" mapTo="SQLRepository">
        <lifetime type="singleton" />
        <constructor>
          <param name="connectionString">
            <value value="ApplicationServices" />
          </param>
        </constructor>
      </type>
    </types>
  </container>
</containers>

This is Unity 2.0 configuration section that I use. As you can see It typeAlias for both my IRepository and my SQLRepository classes and then maps IRepository to SQLRepository. So that anytime IRepository is requested, SQLRepository instance will be supplied. Also, I want to pass a connection string via the constructor to my SQLRepository.

5) So, what am I trying to do?

I am trying to use Unity 2.0 to pass in the instance of IRepository (SQLRepository) to my HomeController. But for some reason the default, parameterless constructor, for the HomeController() gets invoked. But HomeController(IRepository repository) never gets called. I am pretty sure that I did not set things up properly in the web.config file. But I am not sure how do set things up properly so the correct constructor on the HomeController gets called. Please help:)

&Thank you:)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

薄情伤 2024-10-04 10:56:02

您的 Unity 配置看起来不错。问题是您尚未将 Unity 连接到 MVC 框架,因此框架没有使用容器来创建控制器,而是 MVC 使用默认逻辑,该逻辑调用默认构造函数。

你需要两件事。首先,IControllerFactory 的实现。我通常使用这个:

public class UnityControllerFactory : DefaultControllerFactory
{
    private readonly IUnityContainer container;

    public UnityControllerFactory(IUnityContainer container)
    {
        this.container = container;
    }

    protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType)
    {
        if(controllerType != null)
            return container.Resolve(controllerType) as IController;
        return base.GetControllerInstance(requestContext, controllerType);
    }
}

其次,您需要告诉 MVC 框架使用这个控制器工厂而不是默认的控制器工厂。您可以在 Application_Start 处理程序中执行此操作。执行此操作:

ControllerBuilder.Current.SetControllerFactory(
    new UnityControllerFactory(container));

完成此操作后,将通过容器创建您的控制器,并且一切都应该开始工作。

Your Unity configuration looks fine. The problem is that you haven't hooked up Unity to the MVC framework, so the framework isn't using the container to create your controller, instead MVC is using the default logic, which calls the default constructor.

You need two things. First, an implementation of IControllerFactory. I usually use this one:

public class UnityControllerFactory : DefaultControllerFactory
{
    private readonly IUnityContainer container;

    public UnityControllerFactory(IUnityContainer container)
    {
        this.container = container;
    }

    protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType)
    {
        if(controllerType != null)
            return container.Resolve(controllerType) as IController;
        return base.GetControllerInstance(requestContext, controllerType);
    }
}

Second, you need to tell the MVC framework to use this controller factory instead of it's default one. You do this in your Application_Start handler. Do this:

ControllerBuilder.Current.SetControllerFactory(
    new UnityControllerFactory(container));

Once you've done that, your controllers will be created through the container and everything should start working.

好听的两个字的网名 2024-10-04 10:56:02

非常感谢克里斯!!就是这样!以下是使用 Unity 2.0 的 MVC2 中的 Application_Start() 事件的样子:

    protected void Application_Start()
    {
        AreaRegistration.RegisterAllAreas();

        RegisterRoutes(RouteTable.Routes);

        IUnityContainer container = new UnityContainer();

        IControllerFactory controllerFactory = new UnityControllerFactory(container);
        ControllerBuilder.Current.SetControllerFactory(controllerFactory);

        // Do the line below only if you want to Register IoC programatically
        //container.RegisterType<IRepository, SQLRepository>(new ContainerControlledLifetimeManager());

        UnityConfigurationSection section = ConfigurationManager.GetSection("unity") as UnityConfigurationSection;
        section.Configure(container, "Default");
    }

Thank you so much Chris!! That was it! Here's the how the Application_Start() event should look like in MVC2 using Unity 2.0:

    protected void Application_Start()
    {
        AreaRegistration.RegisterAllAreas();

        RegisterRoutes(RouteTable.Routes);

        IUnityContainer container = new UnityContainer();

        IControllerFactory controllerFactory = new UnityControllerFactory(container);
        ControllerBuilder.Current.SetControllerFactory(controllerFactory);

        // Do the line below only if you want to Register IoC programatically
        //container.RegisterType<IRepository, SQLRepository>(new ContainerControlledLifetimeManager());

        UnityConfigurationSection section = ConfigurationManager.GetSection("unity") as UnityConfigurationSection;
        section.Configure(container, "Default");
    }
享受孤独 2024-10-04 10:56:02

尝试使用 Unity.Mvc nuget 包。您可以在UnityConfig类中使用container.LoadConfiguration();

public static class UnityConfig
{
    public static void RegisterComponents()
    {
        var container = new UnityContainer();
        container.LoadConfiguration();
        DependencyResolver.SetResolver(new UnityDependencyResolver(container));
    }
}

然后您可以按如下方式更新 web.config。

<configuration>
  <configSections>
    <section name="unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection, Microsoft.Practices.Unity.Configuration" />
  </configSections>
  <unity configSource="unity.config" />

完整的文章可以在 @ MVC 5 with Unity for 找到依赖注入

Try with Unity.Mvc nuget packages. You can use container.LoadConfiguration(); in UnityConfig class.

public static class UnityConfig
{
    public static void RegisterComponents()
    {
        var container = new UnityContainer();
        container.LoadConfiguration();
        DependencyResolver.SetResolver(new UnityDependencyResolver(container));
    }
}

Then you can update web.config as below.

<configuration>
  <configSections>
    <section name="unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection, Microsoft.Practices.Unity.Configuration" />
  </configSections>
  <unity configSource="unity.config" />

Complete article can be found @ MVC 5 with Unity for Dependency Injection.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文