【问题标题】:Unity DI with MVC 5 in controllers控制器中带有 MVC 5 的 Unity DI
【发布时间】:2017-08-13 02:13:30
【问题描述】:

我目前在尝试在 MVC 控制器中进行依赖注入时遇到问题。

当前的异常如下:

当前类型 myproject.Core.ToolbarLogic 是一个接口,并且 无法构建。您是否缺少类型映射?

调试我意识到这个异常是从这句话引发的(包含在 Razor 视图中):

@{ Html.RenderAction("Toolbar", "Toolbar");  }

在UnityConfig文件中,所有类型都方便注册, 我在控制器中有一个空的构造函数, 异常是从我无法访问调试的地方引发的......而且我已经在 StackOverflow 和 Google 中阅读了很多答案,我不知道现在该尝试什么(我几乎尝试了所有方法)。

有人知道DI有什么问题吗?

代码:

ToolbarController.cs

public class ToolbarController : BaseController
{

    [Dependency]
    public IToolbarLogic ToolbarLogic { get; set; }

    public ToolbarController()
    {
    }


    // GET: Common/Toolbar
    public ActionResult Toolbar()
    {
        bool ShowConfidential = ToolbarLogic.ShowConfidential();
        string linkHome = ToolbarLogic.BindHome(base.User.Identity.Name);
        return PartialView(new ToolbarModel() {
            ShowConfidential = ShowConfidential,
            lnkHome = linkHome
        });
        return PartialView();
    }

}

UnityWebActivator.cs

/// <summary>Provides the bootstrapping for integrating Unity with ASP.NET MVC.</summary>
public static class UnityWebActivator
{
    /// <summary>Integrates Unity when the application starts.</summary>
    public static void Start() 
    {
        var container = UnityConfig.GetConfiguredContainer();

        FilterProviders.Providers.Remove(FilterProviders.Providers.OfType<FilterAttributeFilterProvider>().First());
        FilterProviders.Providers.Add(new UnityFilterAttributeFilterProvider(container));

        DependencyResolver.SetResolver(new UnityDependencyResolver(container));

        // TODO: Uncomment if you want to use PerRequestLifetimeManager
        // Microsoft.Web.Infrastructure.DynamicModuleHelper.DynamicModuleUtility.RegisterModule(typeof(UnityPerRequestHttpModule));
    }

    /// <summary>Disposes the Unity container when the application is shut down.</summary>
    public static void Shutdown()
    {
        var container = UnityConfig.GetConfiguredContainer();
        container.Dispose();
    }
}

UnityConfig.cs

    /// <summary>
/// Specifies the Unity configuration for the main container.
/// </summary>
public class UnityConfig
{
    #region Unity Container
    private static Lazy<IUnityContainer> container = new Lazy<IUnityContainer>(() =>
    {
        var container = new UnityContainer();
        RegisterTypes(container);
        return container;
    });

    /// <summary>
    /// Gets the configured Unity container.
    /// </summary>
    public static IUnityContainer GetConfiguredContainer()
    {
        return container.Value;
    }
    #endregion

    /// <summary>Registers the type mappings with the Unity container.</summary>
    /// <param name="container">The unity container to configure.</param>
    /// <remarks>There is no need to register concrete types such as controllers or API controllers (unless you want to 
    /// change the defaults), as Unity allows resolving a concrete type even if it was not previously registered.</remarks>
    public static void RegisterTypes(IUnityContainer container)
    {
        container.RegisterType<IToolbarLogic, ToolbarLogic>();

        // There is an Unity.config file
        container.LoadConfiguration();
    }
}

Unity.config

<?xml version="1.0"?>
<!-- Configuración de Unity -->
<unity xmlns="http://schemas.microsoft.com/practices/2010/unity">
  <container>


  </container>
</unity>

编辑 1:

正如@Nkosi 所说,我已经评论了LoadConfiguration 行,因为它是有道理的,因为我的Unity.config 中没有任何相关信息(见上文,它是空的)。

错误依旧:

Resolution of the dependency failed, type = "MVCControls.Controllers.ToolbarController", name = "(none)".
Exception occurred while: while resolving.

Exception is: InvalidOperationException - The current type, interfaces_logic.Interfaces.IToolbarLogic, is an interface and cannot be constructed. Are you missing a type mapping?
-----------------------------------------------
At the time of the exception, the container was:

  Resolving MVCControls.Controllers.ToolbarController,(none)
  Resolving value for property ToolbarController.ToolbarLogic
  Resolving interfaces_logic.Interfaces.IToolbarLogic,(none)

【问题讨论】:

  • 你能显示ToolbarLogic的构造函数签名吗?我问是因为错误指出ToolbarLogic(不是IToolbarLogic)是一个接口。
  • 问题是,当给定类型没有注册时,通常会出现此错误。可能是配置文件覆盖了条目,或者 RegisterTypesSetResolver 没有被调用。
  • @rpfc,显示 Unity.config 文件。与 Stefan 建议的类似,我也相信配置被覆盖了。为了测试这个理论,在 RegisterTypes 方法中切换两行,看看它是否解决了问题。
  • 你会评论container.LoadConfiguration(); 行吗?它用于从web.config 文件加载,可能是这个原因。
  • 附带说明,请不要对属性/属性进行 DI。 cuttingedge.it/blogs/steven/pivot/entry.php?id=98

标签: c# asp.net-mvc razor asp.net-mvc-5 unity-container


【解决方案1】:

尝试将控制器的构造函数替换为以下内容:

public ToolbarController(IToolbarLogic toolbarLogic)
{
    this.ToolbarLogic = toolbarLogic;
}

【讨论】:

  • 虽然Unity提供了[Dependency]属性,但我也更喜欢通过构造函数的DI。它使您的系统更加独立于 DI 框架。我不确定这是否会有所帮助。
  • 我已经尝试过了,然后错误是它需要一个无参数的构造函数......
  • @rpfc:该消息通常在 DI 配置不正确时出现。你确定正在调用DependencyResolver.SetResolver 吗?
  • @Stefan 是的.. 它被称为
【解决方案2】:

您的代码中的 cmets 表明存在一个统一配置文件。

在代码中配置后调用container.LoadConfiguration(); 将覆盖配置文件中任何匹配的类型注册。

public static void RegisterTypes(IUnityContainer container) {
    // Register the default type in code
    container.RegisterType<IToolbarLogic, ToolbarLogic>();

    // Override with the config file, if there is a unity section.
    if (ConfigurationManager.GetSection("unity") != null) {
        // There is an Unity.config file
        container.LoadConfiguration();
    }        
}

如果任何其他类型的注册与代码中的任何先前注册都不匹配(如果有),则任何其他类型的注册在加载配置文件后仍然存在。

如果我们有上面的代码和下面的包含统一注册的配置文件

<configuration>
  <configSections>
    <section name="unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection, Microsoft.Practices.Unity.Configuration" />
  </configSections>
  <!-- other config removed for brevity -->
  <unity xmlns="http://schemas.microsoft.com/practices/2010/unity">
    <namespace name="..." />
    <container>
      <register type="IToolbarLogic" />
      <!-- Note the missing mapTo="ToolbarLogic" attribute -->
    </container>
  </unity>
  <!-- other config removed for brevity -->
</configuration>

它没有正确映射IToolbarLogic 接口。如果在代码中注册接口后调用LoadConfiguration扩展方法,那么之前的注册将被覆盖并导致来自OP的错误。

我建议您查看 .config 文件并确保它已正确配置。您还应该确保如果ToolbarLogic 类有任何依赖项,它们也已注册到容器中。 ToolbarLogic 也应该继承自 IToolbarLogic

public class ToolbarLogic : IToolbarLogic {
    //...other code removed for brevity
}

来源:Dependency Injection with Unity

【讨论】:

  • 感谢您的帮助,但我检查了您的所有答案,一切似乎都如您所说...我不知道发生了什么。我已经更新了我的帖子中的信息,请查看
【解决方案3】:

用于解析配置的 mapto 注册条目缺少统一配置

<container>
  <register type="MyService"> ... </register> <!-- Default registration for type MyService -->
  <register type="ILogger" mapTo="EventLogLogger" /> <!-- type mapping -->
  <register type="ILogger" mapTo="PageAdminLogger" name="emergency" /> <!-- named registration -->
</container>

请使用this link了解更多信息。

【讨论】:

  • 这个我已经试过了,还是不行……我觉得在 UnityConfig.cs 类中注册类型就足够了,就像注册和映射类型的两种选择
【解决方案4】:

你可以试试这个

public class ToolbarControllerContext
{
    [Dependency]
    public IToolbarLogic ToolbarLogic { get; set; }
}

public class ToolbarController : BaseController
{    
    private readonly IToolbarLogic _toolbarLogic;

    public ToolbarController(ToolbarControllerContext context)
    {
        _toolbarLogic = context.ToolbarLogic;
    }


    // GET: Common/Toolbar
    public ActionResult Toolbar()
    {
        bool ShowConfidential = _toolbarLogic.ShowConfidential();
        string linkHome = _toolbarLogic.BindHome(base.User.Identity.Name);
        return PartialView(new ToolbarModel() {
            ShowConfidential = ShowConfidential,
            lnkHome = linkHome
        });
        return PartialView();
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-04-09
    • 1970-01-01
    • 1970-01-01
    • 2021-08-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多