根据Castle Windsor教程,我已经使用Castle Windsor与安装程序和设施,早期版本的MVC(pre-6)和WebAPI.
ASP.NET(5)Core已经包括了一些依赖注入支持,但是我仍然没有弄清楚如何连线,我发现的几个示例与以前使用的样本有很大的不同(与安装/设施).大多数例子早于ASP.NET(5)核心最新版本,有些似乎有过时的信息.
它似乎已经从以前的版本组合根设置发生了很大变化,甚至没有Microsoft.Framework.DependencyInjection.ServiceProvider可以解决所有的依赖项,当我将其设置为城堡温莎DI后备.我仍然在挖掘细节,但并不是最新的信息.
我试图使用城堡温莎DI
我找到一个这样的适配器:Github Castle.Windsor DI container.
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.Windsor.dll中出现了“Castle.MicroKernel.ComponentNotFoundException”类型的异常,但未在用户代码中处理
附加信息:没有用于支持服务的组件Microsoft.Framework.Runtime.IAssemblyLoaderEngine被发现
它在城堡后背 – 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(); //
现在我遇到一个例外:
在mscorlib.dll中发生了类型“System.Reflection.TargetInvocationException”的异常,但在用户代码中未处理
尝试获取服务:{Name =“IUrlHelper”FullName =“Microsoft.AspNet.Mvc.IUrlHelper”}
public IRegistration Load(string name,IDictionary arguments) { var serviceFromFallback = _fallbackProvider.GetService(service);
如何前进?
这个尝试将Castle Windsor DI连接到ASP.NET(5)核心中有什么问题?
在Startup.cs中有一个ConfigureServices方法,其返回类型为void.您可以将返回类型更改为ISerivceProvider并返回具体的IServiceProvider,系统将使用新的IServiceProvider作为默认DI容器.以下是AutoFac示例.
public IServiceProvider ConfigureServices(IServiceCollection services) { services.Configure<AppSettings>(Configuration.GetSubKey("AppSettings")); services.AddMvc(); var builder = new ContainerBuilder(); AutofacRegistration.Populate(builder,services); var container = builder.Build(); return container.Resolve<IServiceProvider>(); }
其他DI适配器也实现了类似的接口.您可以尝试自己,但是注意AutoFac现在在beta5中,因此您需要进行一些调整,使您的应用程序运行.
希望这可以帮助