Исключение: InvalidOperationException - текущий тип, является интерфейсом и не может быть сконструирован. Вам не хватает картографирования типов?
В моем загрузчике:
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));
но не использовать
Ответы
Ответ 1
Вы неправильно используете Injection Dependency. Правильный способ состоит в том, чтобы ваши контроллеры принимали нужные им зависимости и уходили в инфраструктуру инъекции зависимостей, введя конкретные экземпляры:
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
Просто для других (таких как я), которые могли столкнуться с вышеупомянутой ошибкой. Решение в простых терминах.
Возможно, вы пропустили регистрацию своего интерфейса и класса (который реализует эту внутреннюю) регистрацию в вашем коде.
например, если ошибка "Текущий тип, xyznamespace. Imyinterfacename, является интерфейсом и не может быть сконструирован. Вам не хватает сопоставления типов? "
Затем вы должны зарегистрировать класс, который реализует Imyinterfacename в классе UnityConfig в методе Реестр. используя следующий код
container.RegisterType<Imyinterfacename, myinterfaceimplclassname>();
Ответ 3
В моем случае я получал эту ошибку, несмотря на регистрацию существующего экземпляра для рассматриваемого интерфейса.
Оказалось, это потому, что я использовал Unity в WebForms через пакет Nuget Unity.WebForms, и я определил Hierarchical Lifetime Manager для зависимости, для которой я предоставлял экземпляр, и все же Transient Life Manager для последующего типа, который зависит от предыдущего типа - обычно это не проблема, - но с Unity.WebForms менеджеры времени жизни работают немного по-другому... Ваши внедренные типы, похоже, требуют иерархического менеджера времени жизни, но новый контейнер по-прежнему создается для каждого веб-запроса ( из-за архитектуры веб-форм, я думаю), как превосходно объяснено в этом посте.
Во всяком случае, я решил это, просто не указав менеджер времени жизни для типов/экземпляров при их регистрации.
т.е.
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)
{
}
...
}
Ответ 4
Может быть, вы не регистрируете контроллеры.
Попробуйте ввести код:
Шаг 1.
Напишите свой собственный контроллер класса factory
ControllerFactory: DefaultControllerFactory путем реализации defaultcontrollerfactory
в папке моделей
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; }
}
}
Шаг 2: зарегистрируйте его в BootStrap:
Метод inBuildUnityContainer
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;
}
Шаг 3:
В Global Asax.
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
WebApiConfig.Register(GlobalConfiguration.Configuration);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
AuthConfig.RegisterAuth();
Bootstrapper.Initialise();
ControllerBuilder.Current.SetControllerFactory(typeof(ControllerFactory));
}
И вы закончили
Ответ 5
В моем случае я использовал 2 разных контекста с контейнером Unitofwork и Ioc, поэтому я вижу, что эта проблема настойчива, пока уровень сервиса пытается сделать второй репозиторий для DI. Причина в том, что существующий модуль содержит другой экземпляр модуля и контейнер, предназначенный для получения вызова из непереработанного нового репозитория. Я пишу здесь для кого-то в моих шагах
Ответ 6
У меня была эта проблема, и причина была в том, что я не добавил пакет Microsoft.Owin.Host.SystemWeb NuGet в свой проект. Хотя код в моем классе запуска был правильным, он не выполнялся.
Поэтому, если вы пытаетесь решить эту проблему, поставьте точку останова в коде, где вы регистрируетесь в Unity. Если вы не нажмете это, ваша инъекция зависимости не сработает.
Ответ 7
Ниже код будет полезен для вас
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;
}