Как начать работу с ASP.NET (5) Core и Castle Windsor для внедрения зависимостей?
Я использовал Castle Windsor с установщиками и средствами в соответствии с руководством Castle Windsor с более ранними версиями MVC (до 6) и WebAPI.
Ядро ASP.NET (5) включило некоторую поддержку внедрения зависимостей, но я до сих пор не выяснил, как именно подключить его, и несколько примеров, которые я обнаружил, выглядят совсем не так, как раньше (с монтажники / услуги). Большинство примеров предшествуют недавнему выпуску ядер ASP.NET (5), а некоторые содержат устаревшую информацию.
Похоже, что радикально изменился по сравнению с предыдущими версиями состав установки root, и даже неMicrosoft.Framework.DependencyInjection.ServiceProvider
может разрешить все зависимости, когда я установлю его как запасной вариант Castle Windsor DI. Я все еще копаюсь в деталях, но там не так много актуальной информации.
Я нашел адаптер, как это:Github Castle.Windsor DI контейнер.
Startup.cs
private static IWindsorContainer container;
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerfactory)
{
container = new WindsorContainer();
app.UseServices(services =>
{
// ADDED app.ApplicationServices FOR FALLBACK DI
container.Populate(services, app.ApplicationServices);
container.BeginScope();
return container.Resolve<IServiceProvider>();
});
// ... default stuff
WindsorRegistration.cs Я добавил несколько строк, чтобы добавить Замок ВиндзорILazyComponentLoader
отступать.
using Castle.MicroKernel.Lifestyle;
using Castle.MicroKernel.Registration;
using Castle.MicroKernel.Resolvers.SpecializedResolvers;
using Castle.Windsor;
using Microsoft.Framework.DependencyInjection;
using System;
using System.Collections.Generic;
using System.Reflection;
namespace Notes.Infrastructure
{
/// <summary>
/// An adapted current autofac code to work with Castle.Windsor container.
/// https://github.com/aspnet/Home/issues/263
/// </summary>
public static class WindsorRegistration
{
public static void Populate(
this IWindsorContainer container,
IEnumerable<IServiceDescriptor> descriptors,
IServiceProvider fallbackProvider // ADDED FOR FALLBACK DI
)
{
// ADDED FOR FALLBACK DI
// http://davidzych.com/2014/08/27/building-the-castle-windsor-dependency-injection-populator-for-asp-net-vnext/
// Trying to add a fallback if Castle Windsor doesn't find the .NET stuff
var fallbackComponentLoader = new FallbackLazyComponentLoader(fallbackProvider);
container.Register(Component.For<ILazyComponentLoader>().Instance(fallbackComponentLoader));
// Rest as usual from the Github link
container.Register(Component.For<IWindsorContainer>().Instance(container));
container.Register(Component.For<IServiceProvider>().ImplementedBy<WindsorServiceProvider>());
container.Register(Component.For<IServiceScopeFactory>().ImplementedBy<WindsorServiceScopeFactory>());
container.Kernel.Resolver.AddSubResolver(new CollectionResolver(container.Kernel));
Register(container, descriptors);
}
private static void Register(
IWindsorContainer container,
IEnumerable<IServiceDescriptor> descriptors)
{
foreach (var descriptor in descriptors)
{
if (descriptor.ImplementationType != null)
{
// Test if the an open generic type is being registered
var serviceTypeInfo = descriptor.ServiceType.GetTypeInfo();
if (serviceTypeInfo.IsGenericTypeDefinition)
{
container.Register(Component.For(descriptor.ServiceType)
.ImplementedBy(descriptor.ImplementationType)
.ConfigureLifecycle(descriptor.Lifecycle)
.OnlyNewServices());
}
else
{
container.Register(Component.For(descriptor.ServiceType)
.ImplementedBy(descriptor.ImplementationType)
.ConfigureLifecycle(descriptor.Lifecycle)
.OnlyNewServices());
}
}
else if (descriptor.ImplementationFactory != null)
{
var service1 = descriptor;
container.Register(Component.For(descriptor.ServiceType)
.UsingFactoryMethod<object>(c =>
{
var builderProvider = container.Resolve<IServiceProvider>();
return
service1.ImplementationFactory(builderProvider);
})
.ConfigureLifecycle(descriptor.Lifecycle)
.OnlyNewServices());
}
else
{
container.Register(Component.For(descriptor.ServiceType)
.Instance(descriptor.ImplementationInstance)
.ConfigureLifecycle(descriptor.Lifecycle)
.OnlyNewServices());
}
}
}
private static ComponentRegistration<object> ConfigureLifecycle(
this ComponentRegistration<object> registrationBuilder,
LifecycleKind lifecycleKind)
{
switch (lifecycleKind)
{
case LifecycleKind.Singleton:
registrationBuilder.LifestyleSingleton();
break;
case LifecycleKind.Scoped:
registrationBuilder.LifestyleScoped();
break;
case LifecycleKind.Transient:
registrationBuilder.LifestyleTransient();
break;
}
return registrationBuilder;
}
private class WindsorServiceProvider : IServiceProvider
{
private readonly IWindsorContainer _container;
public WindsorServiceProvider(IWindsorContainer container)
{
_container = container;
}
public object GetService(Type serviceType)
{
return _container.Resolve(serviceType);
}
}
private class WindsorServiceScopeFactory : IServiceScopeFactory
{
private readonly IWindsorContainer _container;
public WindsorServiceScopeFactory(IWindsorContainer container)
{
_container = container;
}
public IServiceScope CreateScope()
{
return new WindsorServiceScope(_container);
}
}
private class WindsorServiceScope : IServiceScope
{
private readonly IServiceProvider _serviceProvider;
private readonly IDisposable _scope;
public WindsorServiceScope(IWindsorContainer container)
{
_scope = container.BeginScope();
_serviceProvider = container.Resolve<IServiceProvider>();
}
public IServiceProvider ServiceProvider
{
get { return _serviceProvider; }
}
public void Dispose()
{
_scope.Dispose();
}
}
}
}
Первый сбой и попытка разрешенияИз этого примера я получил:
Исключение типа «Castle.MicroKernel.ComponentNotFoundException» возникло в Castle.Windsor.dll, но не было обработано в коде пользователя. Дополнительная информация: Компонент для поддержки службы Microsoft.Framework.Runtime.IAssemblyLoaderEngine не найден.
Это не было доступно, глядя в отладчике на Castle Fallback -Microsoft.Framework.DependencyInjection.ServiceProvider
(таблица услуг).
Отhttp://davidzych.com/tag/castle-windsor/ Я попытался добавить Fallback, поскольку Windsor не смог разрешить все зависимости ASP.NET.
FallbackLazyComponentLoader.cs
/// <summary>
/// https://github.com/davezych/DependencyInjection/blob/windsor/src/Microsoft.Framework.DependencyInjection.Windsor/FallbackLazyComponentLoader.cs
/// </summary>
public class FallbackLazyComponentLoader : ILazyComponentLoader
{
private IServiceProvider _fallbackProvider;
public FallbackLazyComponentLoader(IServiceProvider provider)
{
_fallbackProvider = provider;
}
public IRegistration Load(string name, Type service, IDictionary arguments)
{
var serviceFromFallback = _fallbackProvider.GetService(service);
if (serviceFromFallback != null)
{
return Component.For(service).Instance(serviceFromFallback);
}
return null;
}
}
Это было на первый взгляд необходимо (чтобы внедрить все зависимости .NET)Я мог бы закомментировать startup.cs app.UseBrowserLink (); чтобы избавиться от исключения IAssemblyLoaderEngine.
if (string.Equals(env.EnvironmentName, "Development", StringComparison.OrdinalIgnoreCase))
{
//app.UseBrowserLink(); //
Теперь я сталкиваюсь с исключением:Исключение типа «System.Reflection.TargetInvocationException» произошло в mscorlib.dll, но не было обработано в коде пользователя
Попытка получить службу: {Name = "IUrlHelper" FullName = "Microsoft.AspNet.Mvc.IUrlHelper"}
public IRegistration Load(string name, Type service, IDictionary arguments)
{
var serviceFromFallback = _fallbackProvider.GetService(service);
Как двигаться вперед?Что плохого в этой попытке подключить Castle Windsor DI к ASP.NET (5) Core?