[ASP.NET Core 3 Disclosure marco] portador sistema de servicio [5]: portador proceso de puesta en servicio [Parte] [ASP.NET Core 3 marco divulgación] portador sistema de servicio [5]: portador proceso de puesta en servicio [Parte I]

Original: [Core el marco ASP.NET 3 descubierta.] Portador de sistema de servicio [5]: al portador proceso de puesta en servicio [Parte I]

 

Nosotros, en el " diseño general [Parte I] " y " el diseño general [próximo] " a través de la introducción de IHostedService, iHost y IHostBuider tres interfaces permiten a los lectores para llevar a cabo el servicio amigas modelos tienen un conocimiento general. A continuación, nos dirigimos al concreto de lo abstracto a ver el sistema de transporte para la realización del modelo es como el aterrizaje. Para entender el modelo del portador por defecto para lograr la única necesidad de entender la interfaz y el valor predeterminado iHost IHostBuilder tipo de implementación en ella. Como puede verse en el UML se muestra a continuación, la implementación predeterminada de la interfaz de estos dos tipos son anfitrión y HostBuilder, Benpian destacará ambos tipos. En esta parte extracto del próximo libro "ASP.NET Core 3 descifrar marco", amigos interesados pueden lectores "" ASP.NET Core 3 marco Secret "Bienvenido a" unirse a los lectores de libros

10-9

En primer lugar, el servicio de acogida

Host es el tipo por defecto de la aplicación iHost de la interfaz, es sólo la definición de un tipo de paquete interno NuGet "Microsoft.Extensions.Hosting" en, porque vamos a ser la última participación de tipo estático pública del mismo nombre en esta sección, en el propensas de confusión, lo llamaremos "tipo de instancia de host" para mostrar la diferencia. Antes de la realización presentación formal de tipo Host, primero tenemos que entender dos tipos relacionados, uno de los cuales es HostOptions relacionados opciones de configuración portador. El siguiente fragmento de código, HostOptions sólo contiene un atributo único shutdownTimeout significa Host cerrado objeto de tiempo de espera, su valor predeterminado es de 5 segundos.

HostOptions clase pública 
{ 
    público TimeSpan shutdownTimeout {get; conjunto; } = TimeSpan.FromSeconds (5); 
}

Nosotros, en el " diseño general [Parte I] " se ha reunido una aplicación portador relacionada con el ciclo de vida de interfaces IHostApplicationLifetime, anfitrión se refiere también a otro tipo asociado con el ciclo de vida de IHostLifetime interfaz. Cuando llamamos al método StartAsync objeto host que se iniciará, lo que primero llame a los servicios WaitForStartAsync método IHostLifetime. Cuando StopAsync métodos de objeto host en el proceso de implementación, si se cerró con éxito todos los servicios alojados, se denomina método de los servicios de registro StopAsync IHostLifetime.

interfaz pública IHostLifetime 
{ 
    Tarea WaitForStartAsync (CancellationToken CancellationToken); 
    Tarea StopAsync (CancellationToken CancellationToken); 
}

En el " servicio portador [próximo] prolongado tiempo de" un programa de demostración de registro, el programa se iniciará después de las tres de salida de la información de nivel de registro de la consola, el contenido de los cuales el primer registro fue "Aplicación comenzado. Presione Ctrl + C se apague.", los dos que son la información del entorno de salida de la ruta de conducción de corriente de los archivos de directorio raíz y almacenar contenido. Antes de la aplicación está cerrada, aparecerá en la consola un mensaje que dice "Aplicación se está cerrando ..." log. El cuatro por encima del registro de salida de escala sobre los efectos de la consola se reflejan en la siguiente figura.

10-10

Cuatro de registro se muestra más arriba son de salida como la ConsoleLifetime objetivo, ConsoleLifetime lograr interfaz de tipo IHostLifetime. Además de la información de estado de salida asociado con las aplicaciones de transporte de corriente que no sean en forma de troncos, la captura de la tecla de Cancelar (Ctrl + C), y luego se cierra la aplicación actual función también se implementa en tipo ConsoleLifetime. opciones de configuración ConsoleLifetime definidos en ConsoleLifetimeOptions tipo empleado, el tipo de miembro único atributo se utiliza para determinar si o no los cuatro SuppressStatusMessages registro que se va de salida.

ConsoleLifetime clase pública: IHostLifetime, IDisposable 
{ 
    ConsoleLifetime pública (iOptions <ConsoleLifetimeOptions> opciones, el medio ambiente IHostEnvironment, IHostApplicationLifetime applicationLifetime); 
    ConsoleLifetime pública (iOptions <ConsoleLifetimeOptions> opciones, el medio ambiente IHostEnvironment, IHostApplicationLifetime applicationLifetime, ILoggerFactory loggerFactory); 

    Tarea StopAsync pública (CancellationToken CancellationToken); 
    Tarea WaitForStartAsync pública (CancellationToken CancellationToken); 
    Desechar public void (); 
} 

ConsoleLifetimeOptions clase pública 
{ 
    SuppressStatusMessages public bool {get; conjunto; } 
}

El siguiente código de fragmentos de muestra el tipo Host definición simplificada. tipo de host de inyección de dependencias constructor de una serie de servicios, incluyendo como un contenedor de inyección de dependencias IServiceProvider objeto para iniciar la sesión ILogger <host> objetos y proporcionar opciones iOptions <HostOptions> objetos, y dos con el ciclo de vida de relacionada IHostApplicationLifetime objetos y IHostLifetime objetos. Vale la pena mencionar que el tipo requiere IHostApplicationLifetime objetivo aquí es ApplicationLifetime, ya que tiene que llamar a su método NotifyStarted y NotifyStopped a notificar a los suscriptores después de inicio de la aplicación y el apagado, pero estos métodos no están definidos en la interfaz IHostApplicationLifetime en.

Anfitrión de clases interna: iHost 
{ 
    privado de sólo lectura ILogger <host> _logger; 
    _hostLifetime IHostLifetime sólo lectura privada; 
    _applicationLifetime ApplicationLifetime sólo lectura privada; 
    _options HostOptions de sólo lectura privadas; 
    privadas IEnumerable <> IHostedService _hostedServices; 

    Servicios públicos IServiceProvider {get; } 

    Host público (servicios IServiceProvider, IHostApplicationLifetime applicationLifetime, ILogger <host> registrador, IHostLifetime hostLifetime, iOptions <HostOptions> Opciones) 
    { 
        Services = servicios; 
        _applicationLifetime = (ApplicationLifetime) applicationLifetime; 
        _logger = registrador; 
        _hostLifetime = hostLifetime;
        _options = options.Value); 
    } 

    Pública asíncrono de tareas StartAsync (CancellationToken CancellationToken = por defecto) 
    { 
        esperan ser _hostLifetime.WaitForStartAsync (CancellationToken); 
        cancellationToken.ThrowIfCancellationRequested (); 
        _hostedServices = Services.GetService <IEnumerable <IHostedService >> (); 
        foreach (hostedService var en _hostedServices) 
        { 
            await hostedService.StartAsync (CancellationToken) .ConfigureAwait (false); 
        } 
        _ApplicationLifetime .NotifyStarted (?); 
    } 

    Asíncrono pública de tareas StopAsync (CancellationToken CancellationToken = por defecto) 
    {
        usando (cts var = new CancellationTokenSource (_options.ShutdownTimeout)) 
        usando (linkedCts var = CancellationTokenSource.CreateLinkedTokenSource (cts.Token, CancellationToken)) 
        { 
            var token = linkedCts.Token; 
            _applicationLifetime .StopApplication (?); 
            foreach (hostedService var en _hostedServices.Reverse ()) 
            { 
                await hostedService.StopAsync (token) .ConfigureAwait (false); 
            } 

            Token.ThrowIfCancellationRequested (); 
            await _hostLifetime.StopAsync (token); 
            _applicationLifetime .NotifyStopped (?); 
        } 
    }
 
    Public void Dispose () => (Servicios como IDisposable) ?. Dispose (); 
}

En StartAsync implementado en, anfitrión Objetos pionero en un método llamado objeto WaitForStartAsync IHostLifetime. Si el tipo de registro del servicio de ConsoleLifetime, registrará la salida de tres anteriormente mencionado. Mientras tanto, ConsoleLifetime objeto consola también registrado evento clave, y su objeto es garantizar que cuando el usuario presiona el cancelar aplicaciones clave combinación (Ctrl + C) para ser normalmente cerrado.

Anfitrión objetos usando una dependencia del objeto extraído IServiceProvider objeto contenedor que representa todo servicio portador IHostedService, y empezar a ellas por el método StartAsync. Cuando todos los servicios portadores se inician correctamente, objeto NotifyStarted método ApplicationLifetime se invoca, esta vez los suscriptores recibirán aplicación de notificación comenzó. Una cosa importante tener en cuenta que: Todos IHostedService objeto que representa el servicio portador es "uno por uno (no concurrentes)" está activada, pero sólo después de esperar para todos los servicios portadores se comenzó todo, nuestra aplicación empezó a tener éxito. A lo largo del proceso de inicio, si se utiliza como parámetro se recibe solicitud de cancelación CancellationToken, para iniciar los aborta la operación.

Cuando se llama al método objeto host StopAsync, se llamará ApplicationLifetime método de objeto stopApplication de aplicación de notificación externa está a punto de cerrarse, después de lo cual se llamará método StopAsync para cada objeto IHostedService. Método NotifyStopped cuando todos los servicios portadores se cerraron con éxito, objetos anfitrión tendrá que llamar a objetos IHostLifetime StopAsync y ApplicationLifetime objetos. En el proceso de cierre Host, si el tiempo de espera se excede opción de configuración HostOptions por, o con una solicitud de cancelación se recibe parámetros CancellationToken, se abortará el proceso.

En segundo lugar, el ajuste para la configuración del sistema de

Como un servicio iHost host de destino está siempre fuera del edificio a través de la correspondiente IHostBuilder objetos encima del anfitrión tipo correspondiente cuenta de tipo IHostBuilder HostBuilder , próximo que vamos a explorar cómo los objetos HostBuilder anfitrión se construyen objetos fuera. Además de método de aumento de la construcción objeto iHost, interfaz IHostBuilder también define un conjunto de métodos para que podamos hacer que el objetivo preestablecido apropiado iHost oferta final, estos ajustes se aplican en caché finalmente con el método de construcción.

Vamos a empezar con la configuración de HostBuilder para la configuración del sistema. El siguiente fragmento de código, ConfigureHostConfiguration método para la configuración de host y orientadas ConfigureAppConfiguration aplicaciones orientadas a objetos de delegado están configurados para proporcionar un método de almacenado temporalmente en el conjunto correspondiente de los objetos, los campos correspondientes son configureHostConfigActions y configureAppConfigActions.

HostBuilder clase pública: IHostBuilder 
{ 
    Lista privada <Acción <IConfigurationBuilder >> _configureHostConfigActions = new List <Acción <IConfigurationBuilder >> (); 
    Lista privada <Acción <HostBuilderContext, IConfigurationBuilder >> _configureAppConfigActions = new List <Acción <HostBuilderContext, IConfigurationBuilder >> (); 

    pública IDictionary <objeto, objeto> Propiedades {get; } = New Dictionary <objeto, objeto> (); 

    pública IHostBuilder ConfigureHostConfiguration (Acción <IConfigurationBuilder> configureDelegate) 
    { 
        _configureHostConfigActions.Add (configureDelegate); 
        devolver este; 
    } 

    Pública IHostBuilder ConfigureAppConfiguration (
        Acción <HostBuilderContext, IConfigurationBuilder> configureDelegate) 
    { 
        _configureAppConfigActions.Add (configureDelegate); 
        devolver este; 
    } 
    ... 
}

Muchos métodos de interfaces de IHostBuilder están asociados con la inyección de dependencia. Conjunto de marco de inyección de dependencias se refleja principalmente en dos aspectos: En primer lugar, utilizando el método de añadir el registro del servicio ConfigureServices, en segundo lugar, el uso de UseServiceProviderFactory <TContainerBuilder> método de dos registrada IServiceProviderFactory <TContainerBuilder> planta, y el uso de ConfigureContainer <TContainerBuilder> partido fábrica ContainerBuilder crea más ajustes.

, servicios de terceros que dependen del registro

En cuanto a la instalación y configuración del sistema, ConfigureServices proceso de registro de los servicios dependientes de Acción <HostBuilderContext, IServiceCollection> objeto delegado se almacena temporalmente en el mismo conjunto de campos que corresponden a configureServicesActions representados, que el tiempo se utilizará en el proceso de construcción.

HostBuilder clase pública: IHostBuilder 
{ 
    Lista privada <Acción <HostBuilderContext, IServiceCollection >> _configureServicesActions = new List <Acción <HostBuilderContext, IServiceCollection >> (); 

    pública IHostBuilder ConfigureServices (Acción <HostBuilderContext, IServiceCollection> configureDelegate) 
    { 
        _configureServicesActions.Add (configureDelegate); 
        devolver este; 
    } 
    ... 
}

Además del método de dirigir las llamadas interfaces de servicio ConfigureServices IHostBuilder están registrados, también podemos llamar a los métodos siguientes para completar el registro de estas extensiones para algunos servicios especiales. Dos ConfigureLogging sobrecargas método de extensión nos ayudan registrados para el registro de los servicios relacionados con el marco, dos UseConsoleLifetime método de extensión está sobrecargado para agregar ConsoleLifetime de registro de servicio, dos RunConsoleAsync de extensión de base sobrecargas de método en los servicios de registro en más ConsoleLifetime construcción y puesta objeto iHost como anfitrión.

HostingHostBuilderExtensions clase public static 
{ 
    public static IHostBuilder ConfigureLogging (esto IHostBuilder hostBuilder, Acción <HostBuilderContext, ILoggingBuilder> configureLogging) 
    => hostBuilder.ConfigureServices ((contexto, colección) => collection.AddLogging (constructor => configureLogging (contexto, constructor))) ; 

    public static IHostBuilder ConfigureLogging (esto IHostBuilder hostBuilder, Acción <ILoggingBuilder> configureLogging) 
    => hostBuilder.ConfigureServices ((contexto, colección) => collection.AddLogging (constructor => configureLogging (constructor))); 

    public static IHostBuilder UseConsoleLifetime (esto hostBuilder IHostBuilder)
    => HostBuilder.ConfigureServices ((contexto, colección) => collection.AddSingleton <IHostLifetime, ConsoleLifetime> ()); 

    public static IHostBuilder UseConsoleLifetime (esto IHostBuilder hostBuilder, Acción <ConsoleLifetimeOptions> configureOptions) 
    => hostBuilder.ConfigureServices ((contexto, colección) => 
        { 
            collection.AddSingleton <IHostLifetime, ConsoleLifetime> (); 
            collection.Configure (configureOptions); 
        }); 

    public static Tarea RunConsoleAsync (esto IHostBuilder hostBuilder, CancellationToken CancellationToken = por defecto) 
    => hostBuilder.UseConsoleLifetime () Generar () RunAsync (CancellationToken)..;

    public static Tarea RunConsoleAsync (esto IHostBuilder hostBuilder, Acción <ConsoleLifetimeOptions> configureOptions, CancellationToken CancellationToken = por defecto) 
    => hostBuilder.UseConsoleLifetime (configureOptions) .build () RunAsync (CancellationToken).; 
}

En cuarto lugar, el registro IServiceProviderFactory <TContainerBuilder>

IServiceProvider objetos una dependencia del recipiente se IServiceProviderFactory siempre crea registrado <TContainerBuilder> fábrica. Desde UseServiceProviderFactory <TContainerBuilder> método de registro IServiceProviderFactory <TContainerBuilder> es un objeto genérico, así convertidos HostBuilder a un tipo de interfaz de la siguiente manera IServiceFactoryAdapter esta adaptación. Como se muestra en el segmento de código a continuación, es sólo el tipo de objeto convert ContainerBuilder solamente. ServiceFactoryAdapter <TContainerBuilder> Tipo IServiceFactoryAdapter es la interfaz por defecto de lograr.

ServiceFactoryAdapter clases interna <TContainerBuilder>: IServiceFactoryAdapter 
{ 
    privado IServiceProviderFactory <TContainerBuilder> _serviceProviderFactory; 
    sólo lectura privada Func <HostBuilderContext> _contextResolver; 
    privada Func <HostBuilderContext, IServiceProviderFactory <TContainerBuilder >> _factoryResolver; 

    ServiceFactoryAdapter pública (IServiceProviderFactory <TContainerBuilder> serviceProviderFactory) 
    => _serviceProviderFactory = serviceProviderFactory; 

    ServiceFactoryAdapter pública (Func <HostBuilderContext> contextResolver, Func <HostBuilderContext, IServiceProviderFactory <TContainerBuilder >> factoryResolver) 
    { 
        _contextResolver = contextResolver;
        _factoryResolver = factoryResolver; 
    } 

    Objeto CreateBuilder pública (servicios IServiceCollection) 
        => _serviceProviderFactory ?? . _factoryResolver (_contextResolver ()) CreateBuilder (servicios); 

    pública IServiceProvider CreateServiceProvider (ContainerBuilder objeto) 

        => _serviceProviderFactory.CreateServiceProvider ((TContainerBuilder) ContainerBuilder); 
}

Definir dos UseServiceProviderFactory <TContainerBuilder> sobrecargado muestra a continuación, Func IServiceProviderFactory un primer método de proporcionar sobrecarga <TContainerBuilder> objetos y proporciona un segundo método de sobrecarga <HostBuilderContext, IServiceProviderFactory <TContainerBuilder >> es convertida en un ServiceFactoryAdapter <TContainerBuilder> objeto y almacenada temporalmente por el campo _serviceProviderFactory. Si UseServiceProviderFactory <TContainerBuilder> método no es llamado, campo de rentabilidad _serviceProviderFactory será confeccionado de acuerdo con el objeto DefaultServiceProviderFactory ServiceFactoryAdapter <IServiceCollection> código objeto fragmento que se muestra a continuación también refleja esto.

HostBuilder clase pública: IHostBuilder 
{ 
    Lista privada <IConfigureContainerAdapter> _configureContainerActions = new List <IConfigureContainerAdapter> (); 
    privada IServiceFactoryAdapter _serviceProviderFactory = new ServiceFactoryAdapter <IServiceCollection> (nueva DefaultServiceProviderFactory ()); 

    pública IHostBuilder UseServiceProviderFactory <TContainerBuilder> (IServiceProviderFactory <TContainerBuilder> fábrica) 
    { 
        _serviceProviderFactory = new ServiceFactoryAdapter <TContainerBuilder> (fábrica); 
        devolver este; 
    } 

    Pública IHostBuilder UseServiceProviderFactory <TContainerBuilder> (Func <HostBuilderContext, IServiceProviderFactory <TContainerBuilder >>
        _serviceProviderFactory = new ServiceFactoryAdapter <TContainerBuilder> (() => _hostBuilderContext, de fábrica)); 
        devolver este; 
    } 
}

TContainerBuilder registro objeto IServiceProviderFactory <TContainerBuilder> fábricas puede ser proporcionado por más ConfigureContainer <TContainerBuilder> método, se realiza mediante el establecimiento de la específica acción proporcionado <HostBuilderContext, TContainerBuilder> objeto. Este objeto delegado genérico también necesita hacer una adaptación similar con el fin de ser almacenados temporalmente, con el tiempo se pueden convertir en los siguientes tipos de interfaz IConfigureContainerAdapter, esta adaptación es la esencia de un objeto convierte TContainerBuilder tipo Object. ConfigureContainerAdapter <TContainerBuilder> tipo que se muestra a continuación es la implementación predeterminada de esta interfaz.

interfaz interna IServiceFactoryAdapter 
{ 
    objeto CreateBuilder (servicios IServiceCollection); 
    IServiceProvider CreateServiceProvider (objeto ContainerBuilder); 
} 

IConfigureContainerAdapter interfaz interna 
{ 
    void ConfigureContainer (HostBuilderContext hostContext, objeto ContainerBuilder); 
} 

De clases interna ConfigureContainerAdapter <TContainerBuilder>: IConfigureContainerAdapter 
{ 
    acción privada <HostBuilderContext, TContainerBuilder> _action; 
    ConfigureContainerAdapter pública (Acción <HostBuilderContext, TContainerBuilder> acción) 
        => _action = acción;
    ConfigureContainer pública vacío (HostBuilderContext hostContext, objeto ContainerBuilder) 
        => _action (hostContext, (TContainerBuilder) ContainerBuilder); 
}

Se define como sigue ConfigureContainer <TContainerBuilder> métodos, nos encontramos con que el método proporcionará la acción <HostBuilderContext, TContainerBuilder> objetos seleccionados en ConfigureContainerAdapter <> TContainerBuilder objetos, y se añade a la colección representada por configureContainerActions campo.

HostBuilder clase pública: IHostBuilder 
{ 
    Lista privada <IConfigureContainerAdapter> _configureContainerActions = new List <IConfigureContainerAdapter> (); 
    pública IHostBuilder ConfigureContainer <TContainerBuilder> (Acción <HostBuilderContext, TContainerBuilder> configureDelegate) 
    { 
        _configureContainerActions.Add (nueva ConfigureContainerAdapter <TContainerBuilder> (configureDelegate)); 
        devolver este; 
    } 
    ... 
}

En quinto lugar, la integración con el marco de inyección de dependencia de terceros

Somos " una versión mini del marco de inyección de dependencias para crear una versión simple llamado Gato marco de inyección de dependencias, y" "en el marco de la inyección de dependencia de terceros para la adaptación " para crear un IServiceProviderFactory para ello <TContainerBuilder> lograrse, tipos específicos CatServiceProvider, a continuación, te mostramos cómo depender de terceros para integrarse con el marco de la inyección del gato por el registro de esta CatServiceProvider. Si está utilizando el marco del gato, podemos marcar características MapToAttribute del tipo de servicio en la forma de definir la información de registro del servicio. En el programa de demostración se creó de tal manera que usamos la definición de los tres servicios (Foo, Bar y Baz) y la correspondiente interfaz (IFoo, Ibar y IBaz).

IFoo interfaz pública {} 
interfaz pública IBar {} 
interfaz pública IBaz {} 

[MapTo (typeof (IFoo), Lifetime.Root)] 
public class Foo: IFoo {} 

[MapTo (typeof (IBar), Lifetime.Root)] 
public class bar: IBar {} 

[MapTo (typeof (IBaz), Lifetime.Root)] 
public class Baz: IBaz {}

FakeHostedService como se ilustra a continuación sirven nuestra aplicación de demostración que se encuentra alojado. Hemos inyectado tres servicios definidos anteriormente en el constructor, el constructor ofrece aserción de depuración para asegurar que estos tres servicios se inyectan con éxito.

pública FakeHostedService sellada clase: IHostedService 
{ 
    FakeHostedService pública (IFoo foo, IBar bar, IBaz Baz) 
    { 
        Debug.Assert; (foo! = null) 
        Debug.Assert (barra! = Null); 
        Debug.Assert (Baz! = Null); 
    } 
    StartAsync pública de tareas (CancellationToken CancellationToken) => Task.CompletedTask; 
    Tarea StopAsync pública (CancellationToken CancellationToken) => Task.CompletedTask; 
}

En el servicio de llevar el programa se muestra a continuación, creamos un objeto HostBuilder y los servicios registrados a FakeHostedService a cargo de la llamada al método ConfigureServices. Nuestro método UseServiceProviderFactory siguiente llamada de CatServiceProvider completado el registro, y luego llama al método de Registro CatBuilder completó la mayor parte del registro de servicio para la entrada de la asamblea. Cuando llamamos método de aumento HostBuilder de construcción del host de destino como anfitrión y ponerlo en marcha, FakeHostedService servicio alojado, se creará automáticamente y se inicia. (El código fuente aquí descarga)

class Program 
{ 
    static void Main () 
    { 
        nueva HostBuilder () 
            .ConfigureServices (SVC => svcs.AddHostedService <FakeHostedService> ()) 
            .UseServiceProviderFactory (nueva CatServiceProviderFactory ()) .ConfigureContainer <CatBuilder> (constructor => builder.Register (Asamblea .GetEntryAssembly ())) 
            .build () 
            .Llevar (); 
    } 
}
            

Servicio portador sistema [1]: un servicio portador de larga duración [Parte]
servicio portador del sistema [2]: servicios portadores tiempo de funcionamiento [próximo]
servicio portador sistema [3]: Diseño general [Parte]
servicio portador sistema [4]: diseño general [Parte II]
servicio portador sistema de [5]: portador proceso de puesta en servicio [Parte]
servicio portador sistema [6]: portador proceso de puesta en servicio [Parte II]

Supongo que te gusta

Origin www.cnblogs.com/lonelyxmas/p/12451799.html
Recomendado
Clasificación