例外情况是:InvalidOperationException - 当前类型,是一个接口,无法构造.你错过了类型映射吗?

Ela*_*nda 32 c# asp.net-mvc inversion-of-control unity-container

在我的引导程序中:

namespace Conduit.Mam.ClientServices.Common.Initizliaer
{
    public static class Initializer
    {
        private static bool isInitialize;
        private static readonly object LockObj = new object();
        private static IUnityContainer defaultContainer = new UnityContainer();

        static Initializer()
        {
            Initialize();
        }

        public static void Initialize()
        {
            if (isInitialize)
                return;

            lock (LockObj)
            {
                IUnityContainer container = defaultContainer;

                //registering Unity for MVC
                DependencyResolver.SetResolver(new UnityDependencyResolver(container));

                //registering Unity for web API
                //  GlobalConfiguration.Configuration.DependencyResolver = new Unity.WebApi.UnityDependencyResolver(container);

                #region managers
                container.RegisterType<ISettingsManager, SettingsManager>();

                container.RegisterType<IMamDataManager, MamDataManager>();

                container.RegisterType<IAppsDataManager, AppsDataManager>();
                #endregion

                if (!isInitialize)
                {
                    isInitialize = true;
                }
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

在我的控制器代码中:

ISettingsManager sm = mUnityContainer.Resolve<ISettingsManager>();
Run Code Online (Sandbox Code Playgroud)

悬停在mUnityContainer上我看到ISettingsManager映射到SettingsManager

但后来我得到了错误:

例外情况是:InvalidOperationException - 当前类型,是一个接口,无法构造.你错过了类型映射吗?

我也试过了

ISettingsManager sm = (ISettingsManager)mUnityContainer.Resolve<>(typeof(ISettingsManager));
Run Code Online (Sandbox Code Playgroud)

但没用

Ram*_*Ram 33

只为其他人(像我一样)可能遇到上述错误.解决方案简单来说.

您可能错过了在代码中注册接口和类(实现该接口)注册.

如果错误是如
" 当前类型,xyznamespace.Imyinterfacename,是一个接口,不能构成.是否缺少类型映射?"

然后,你必须注册它实现了类ImyinterfacenameUnityConfig类中的注册方法.使用如下代码

 container.RegisterType<Imyinterfacename, myinterfaceimplclassname>();
Run Code Online (Sandbox Code Playgroud)

  • 我试着用这个,但它不起作用:( (3认同)

Dar*_*rov 17

您错误地使用了依赖注入.正确的方法是让你的控制器获取他们需要的依赖关系并留给依赖注入框架注入具体实例:

public class HomeController: Controller
{
    private readonly ISettingsManager settingsManager;
    public HomeController(ISettingsManager settingsManager)
    {
        this.settingsManager = settingsManager;
    }

    public ActionResult Index()
    {
        // you could use the this.settingsManager here
    }
}
Run Code Online (Sandbox Code Playgroud)

正如您在此示例中所看到的,控制器对容器一无所知.那应该是这样的.

所有DI接线都应该在Bootstraper中进行.你永远不应该container.Resolve<>在你的代码中使用调用.

就您的错误而言,mUnityContainer您在控制器中使用的可能与Bootstraper中构建的实例不同.但是,由于您不应该在控制器中使用任何容器代码,因此这应该不再是问题.

  • 这不回答这个问题.这个"答案"只能说明问题本身的优点; 它只在评论中.关于模式的"最佳实践"讨论属于programmers.stackexchange.com. (15认同)
  • 您如何建议我们解决Global.asax.cs文件中的依赖项?当然我们不能将它注入构造函数中.这个答案是彻头彻尾的错误和错误信息 (5认同)

Bre*_*eno 8

在我的情况下,尽管注册了相关接口的现有实例,但我收到此错误.

原来,这是因为我通过Unity.WebForms Nuget包在WebForms中使用Unity ,并且我为我提供实例的依赖项指定了一个Hierarchical Lifetime管理器,但是后续类型的Transient生命周期管理器依赖于以前的类型 - 通常不是问题 - 但使用Unity.WebForms,生命周期管理器的工作方式略有不同......您注入的类型似乎需要一个Hierarchical生命周期管理器,但仍然为每个Web请求创建一个新容器(因为Web窗体架构的我猜的)作为出色解释这个职位.

无论如何,我通过在注册时没有为类型/实例指定生命周期管理器来解决它.

container.RegisterInstance<IMapper>(MappingConfig.GetMapper(), new HierarchicalLifetimeManager());    
container.RegisterType<IUserContext, UserContext>(new TransientLifetimeManager());
Run Code Online (Sandbox Code Playgroud)

container.RegisterInstance<IMapper>(MappingConfig.GetMapper());
container.RegisterType<IUserContext, UserContext>();
Run Code Online (Sandbox Code Playgroud)

这样可以在这里成功解决IMapper:

public class UserContext : BaseContext, IUserContext
{
    public UserContext(IMapper _mapper) : base(_mapper)
    {

    }
    ...
}
Run Code Online (Sandbox Code Playgroud)