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

时间:2013-01-27 15:59:07

标签: 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;
                }
            }
        }
    }
}

在我的控制器代码中:

ISettingsManager sm = mUnityContainer.Resolve<ISettingsManager>();

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

然后我收到错误:

  

异常是:InvalidOperationException - 当前类型,是   界面,不能构造。你错过了类型映射吗?

我也试过

ISettingsManager sm = (ISettingsManager)mUnityContainer.Resolve<>(typeof(ISettingsManager));

但没有用

7 个答案:

答案 0 :(得分:30)

对于可能遇到上述错误的其他人(比如我)。简单来说就是解决方案。

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

例如,如果错误是
  &#34; 当前类型,xyznamespace。 Imyinterfacename ,是一个无法构造的接口。您是否缺少类型映射? &#34;

然后您必须在 注册 UnityConfig 类中注册实现 Imyinterfacename 的类> 方法。使用如下代码

 container.RegisterType<Imyinterfacename, myinterfaceimplclassname>();

答案 1 :(得分: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
    }
}

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

所有DI接线都应该在Bootstraper中进行。您绝不应在代码中使用container.Resolve<>次来电。

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

答案 2 :(得分:7)

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

原来,这是因为我通过Unity.WebForms Nuget包在WebForms中使用Unity,并且我为我提供实例的依赖项指定了一个Hierarchical Lifetime管理器,但是一个Transient生命周期管理器对于依赖于先前类型的后续类型 - 通常不是问题 - 但使用Unity.WebForms,生命周期管理器的工作方式略有不同......您注入的类型似乎需要一个Hierarchical生命周期管理器,但仍会创建一个新容器对于每个Web请求(因为我猜的Web表单的体系结构),正如this post中所解释的那样。

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

container.RegisterInstance<IMapper>(MappingConfig.GetMapper(), new HierarchicalLifetimeManager());    
container.RegisterType<IUserContext, UserContext>(new TransientLifetimeManager());

变为

container.RegisterInstance<IMapper>(MappingConfig.GetMapper());
container.RegisterType<IUserContext, UserContext>();

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

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

    }
    ...
}

答案 3 :(得分:0)

可能是您没有注册控制器。 请尝试以下代码:

第1步。 编写自己的控制器工厂类 ControllerFactory:通过实现defaultcontrollerfactory实现DefaultControllerFactory 在模型文件夹

=IF(AND(ISNUMBER(MATCH(A2,$E$2:$E$4,0)), ISNUMBER(MATCH(B2,$G$2:$G$3,0))),"TRUE","FALSE")

第2步:在BootStrap中对它进行Regigster: inBuildUnityContainer方法

  public class ControllerFactory :DefaultControllerFactory
    {
    protected override IController GetControllerInstance(RequestContext         requestContext, Type controllerType)
        {
            try
            {
                if (controllerType == null)
                    throw new ArgumentNullException("controllerType");

                if (!typeof(IController).IsAssignableFrom(controllerType))
                    throw new ArgumentException(string.Format(
                        "Type requested is not a controller: {0}",
                        controllerType.Name),
                        "controllerType");

                return MvcUnityContainer.Container.Resolve(controllerType) as IController;
            }
            catch
            {
                return null;
            }

        }
        public static class MvcUnityContainer
        {
            public static UnityContainer Container { get; set; }
        }
    }

第3步: 在Global Asax。

private static IUnityContainer BuildUnityContainer()
    {
      var container = new UnityContainer();

      // register all your components with the container here
      // it is NOT necessary to register your controllers

      // e.g. container.RegisterType<ITestService, TestService>();    
      //RegisterTypes(container);
      container = new UnityContainer();
      container.RegisterType<IProductRepository, ProductRepository>();


      MvcUnityContainer.Container = container;
      return container;
    }

你已经完成了

答案 4 :(得分:0)

在我的情况下,我使用了2个不同的上下文与Unitofwork和Ioc容器,所以我看到这个问题坚持,而服务层试图向DI注入第二个存储库。原因是存在模块已经包含其他模块实例和容器应该从未构造的新存储库中获取调用..我在这里为我的shooes中的人写了

答案 5 :(得分:0)

我遇到了这个问题,原因是我没有将Microsoft.Owin.Host.SystemWeb NuGet包添加到我的项目中。尽管启动类中的代码是正确的,但未执行。

因此,如果您要解决此问题,请在执行Unity注册的代码中放置一个断点。如果不执行该操作,则依赖项注入将无法进行。

答案 6 :(得分:0)

下面的代码将对您有所帮助

public static IUnityContainer Initialise(IUnityContainer container = null)
    {
        if (container == null)
        {
            container = new UnityContainer();
        }

container.RegisterType<ISettingsManager, SettingsManager>(); container.Resolve<SettingsManager>(); container.RegisterType<SettingsManagerController>(new InjectionProperty("_SettingManagerProvider", new ResolvedParameter<ISettingManager>())); return container; }