У вас есть три проблемы здесь.
Задача 1. Вы создаете новый контейнер:
using (var container = new UnityContainer())
{
container.Resolve<IMasterDataClient>("MDS");
container.Resolve<ILinksManager>("LDS");
}
Это container
будет пустым и иметь 0 регистраций. Это не тот контейнер, на который вы сделали регистрацию. Существует несколько способов решить эту проблему:
Проблема 1 - Решение 1: Не вводите контейнер. Ввести зависимости. Вместо того, чтобы использовать контейнер, вы должны вводить свои зависимости непосредственно к контроллеру:
public class MyApiController : ApiController
{
IMasterDataClient _masterDataClient;
ILinksManager _linksManager
public MyApiController(IMasterDataClient masterDataClient, ILinksManager linksManager)
{
_masterDataClient = masterDataClient;
_linksManagerlinksManager;
}
}
Таким образом, вы можете избежать службы локатора-модель и вашу зависимость для самого контейнера. Если вы используете именованные регистрации, вам может понадобиться использовать атрибут Dependency
.
With Unity how do I inject a named dependency into a constructor?
Задача 1 - Решение 2: Вводите свой контейнер, а не создавать новый. Если вам действительно нужен ваш контроллер по какой-то причине, вы должны попытаться ввести его вместо этого. Таким образом вы получите тот же контейнер, что и для ваших регистраций.
public class MyApiController : ApiController
{
IUnityContainer _container;
public MyApiController(IUnityContainer container)
{
_container = container;
}
}
Задача 1 - Решение 3: Держите статическую ссылку на свой контейнер. В качестве последнего средства вы можете сохранить свой контейнер как статический экземпляр.
public static class IocContainer
{
private static readonly Lazy<IUnityContainer> Container = new Lazy<IUnityContainer>(() =>
{
var container = new UnityContainer();
return container;
});
public static IUnityContainer Instance
{
get { return Container.Value; }
}
}
И в вашей регистрации:
public static class UnityConfig
{
public static void RegisterComponents()
{
var container = IocContainer.Instance;
// register all your components with the container here
// it is NOT necessary to register your controllers
// e.g. container.RegisterType<ITestService, TestService>();
myContainer.RegisterType<IMasterDataClient, MasterDataClient>("MDS");
myContainer.RegisterType<ILinksManager, LinksManager>("LDS");
GlobalConfiguration.Configuration.DependencyResolver = new UnityDependencyResolver(container);
}
}
Использование:
IocContainer.Instance.Resolve<IMasterDataClient>("MDS");
Задача 2.Кажется, вы не регистрируете зависимости для MasterDataClient
.
Имеет зависимости от IApiClient
и IUriDispenser
. Они также должны быть зарегистрированы.
Задача 3. Вы назначаете распознаватель зависимость к неправильному контейнера
Вы в настоящее время создать два контейнера - myContainer
и container
. Вы делаете регистрацию в одном контейнере, а затем используете другой номер DependencyResolver
. Вы можете решить эту проблему, удалив myContainer
и используйте только container
. В противном случае вы не сможете использовать свои регистрации в Web Api.
public static class UnityConfig
{
public static void RegisterComponents()
{
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>();
container.RegisterType<IMasterDataClient, MasterDataClient>("MDS");
container.RegisterType<ILinksManager, LinksManager>("LDS");
GlobalConfiguration.Configuration.DependencyResolver = new UnityDependencyResolver(container);
}
}
Update:
Я не знаю реализации классов для IApiClient и IUriDispenser, как это партия длл третий так, как я могу зарегистрировать его
Единство должно знать, какую реализацию использовать при разрешении интерфейса. Так почему-то вам нужно сказать Unity, какую реализацию использовать. Там отличный ответ от Mark Seemann в вопросе ниже:
Unity IoC for resolving assemblies dynamically
Она сканирует сборку для реализации своего интерфейса, а затем регистрирует их/его.
В качестве альтернативы вы можете использовать registration by convention, что позволяет сделать несколько регистраций сразу:
container.RegisterTypes(
AllClasses.FromLoadedAssemblies(),
WithMapping.MatchingInterface,
WithName.Default,
WithLifetime.ContainerControlled);
Обратите внимание, что это будет регистрировать все реализации, в том числе свои собственные. Если вы просто хотите реализаций сторонних вы должны быть в состоянии сделать что-то сделать так:
// Get the assemblies where IApiClient exists.
IEnumerable<Assembly> assemblies = AppDomain.CurrentDomain.GetAssemblies()
.Where(x => x.GetTypes().Contains(typeof (IApiClient)));
// Register all implementations based on convention.
container.RegisterTypes(AllClasses.FromAssemblies(assemblies),
WithMappings.FromMatchingInterface,
WithName.Default,
WithLifetime.ContainerControlled); // Maybe another lifetime manager?
Update 2:
Убедитесь, что контроллер имеет открытый конструктор без параметров.
Ошибка выше, может иметь много причин, большинство из них покрыты в этих вопросах:
Unable to inject DBContext into my Web API 2 Controller with Unity
Make sure that the controller has a parameterless public constructor error
error: Make sure that the controller has a parameterless public constructor webapi
В основном это единство говорит вам, что вы» пытаюсь решить что-то, что вы не зарегистрировали. Или что вы еще не зарегистрировали DependencyResolver.
@ Хима - Я обновил свой ответ. – smoksnes
Спасибо .. Я сделал все изменения и применил решение 1 для проблемы 1..but, я получаю 500 ошибок внутреннего сервера – Hima
@Hima - Не могли бы вы поделиться полученной вами ошибкой? – smoksnes