Wie kann ich mit ASP.NET (5) Core und Castle Windsor for Dependency Injection beginnen?

Hintergrund

Ich habe Castle Windsor mit Installern und Einrichtungen gemäß dem Castle Windsor-Tutorial mit früheren Versionen von MVC (vor Version 6) und WebAPI verwendet.

ASP.NET (5) Core hat einige Unterstützung für Dependency Injection enthalten, aber ich habe immer noch nicht genau herausgefunden, wie ich es verkabeln soll, und die wenigen Beispiele, die ich gefunden habe, sehen ganz anders aus als die, mit denen ich es zuvor verwendet habe die Installateure / Einrichtungen). Die meisten Beispiele stammen aus früheren Versionen von ASP.NET (5) und einige scheinen veraltete Informationen zu haben.

Es scheint sich gegenüber der vorherigen Version des Kompositionsstamm-Setups ziemlich radikal geändert zu haben, und nicht einmalMicrosoft.Framework.DependencyInjection.ServiceProvider kann alle Abhängigkeiten auflösen, wenn ich es als Castle Windsor DI-Fallback einstelle. Ich beschäftige mich immer noch mit den Details, aber es gibt nicht viele aktuelle Informationen.

Mein Versuch, Castle Windsor für DI @ zu verwend

Ich habe einen Adapter wie diesen gefunden: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 Ich habe ein paar Zeilen hinzugefügt, um ein Castle Windsor hinzuzufügenILazyComponentLoader Zurückfallen

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();
            }
        }
    }
}
First Schluckauf und Lösungsversuch

Von diesem Beispiel bekam ich:

Eine Ausnahme vom Typ 'Castle.MicroKernel.ComponentNotFoundException' ist in Castle.Windsor.dll aufgetreten, wurde jedoch nicht im Benutzercode behandelt. Zusätzliche Informationen: Keine Komponente zur Unterstützung des Dienstes Microsoft.Framework.Runtime.IAssemblyLoaderEngine gefunden

m Debugger von Castle Fallback konnte nicht gesucht werdeMicrosoft.Framework.DependencyInjection.ServiceProvider (Leistungsverzeichnis).

Vonhttp: //davidzych.com/tag/castle-windsor Ich habe versucht, ein Fallback hinzuzufügen, da Windsor nicht alle ASP.NET-Abhängigkeiten auflösen konnte.

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;
    }
}
Es war anscheinend notwendig (um alle .NET-Abhängigkeiten einzufügen)

Ich könnte startup.cs auskommentieren app.UseBrowserLink (); um die IAssemblyLoaderEngine Ausnahme loszuwerden.

        if (string.Equals(env.EnvironmentName, "Development", StringComparison.OrdinalIgnoreCase))
        {
            //app.UseBrowserLink(); // 
Nun stoße ich auf eine Ausnahme:

Eine Ausnahme vom Typ 'System.Reflection.TargetInvocationException' ist in mscorlib.dll aufgetreten, wurde jedoch im Benutzercode nicht behandelt.

Versuchen, den Dienst abzurufen: {Name = "IUrlHelper" FullName = "Microsoft.AspNet.Mvc.IUrlHelper"}

    public IRegistration Load(string name, Type service, IDictionary arguments)
    {
        var serviceFromFallback = _fallbackProvider.GetService(service);
Wie geht es weiter?

Was ist falsch an diesem Versuch, Castle Windsor DI mit ASP.NET (5) Core zu verbinden?

Antworten auf die Frage(6)

Ihre Antwort auf die Frage