c# castle-windsor asp.net-web-api wcf-web-api

c# - Inyección de dependencias en WebAPI con Castle Windsor



castle-windsor asp.net-web-api (3)

No trabajé directamente con Castle Windsor, pero creo que la lógica debería ser similar:

Su WatchController debería verse así:

public WatchController(IWatch watch) { _watch = watch; }

Y aquí es donde inject la dependencia.

Deberías tener el equivalente a un localizador en el que registras tu clase WatchController y decirle qué reloj debería recibir según lo que desees ... diseño / tiempo de ejecución, día de la semana, número aleatorio ... lo que sea que funcione o lo que sea necesitas...

El siguiente código es de MVVM-Light, pero debe aclarar el párrafo anterior:

static ViewModelLocator() { ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default); // This will run in design mode, so all your VS design data will come from here if (ViewModelBase.IsInDesignModeStatic) { SimpleIoc.Default.Register<IDataService, Design.DesignDataService>(); } // This will run REAL stuff, in runtime else { SimpleIoc.Default.Register<IDataService, DataService>(); } // You register your classes, so the framework can do the injection for you SimpleIoc.Default.Register<MainViewModel>(); ... }

Quiero implementar Dependency Injection en la aplicación WebApi usando Castle Windsor. Tengo el siguiente código de muestra:

Interfaz -

public interface IWatch { { DateTime GetTime(); } }

La siguiente clase Watch implementa la interfaz IWatch -

public class Watch:IWatch { public DateTime GetTime() { return DateTime.Now; } }

Controlador WebApi - WatchController como a continuación -

public class WatchController : ApiController { private readonly IWatch _watch; public WatchController() { _watch = new Watch(); } //http://localhost:48036/api/Watch public string Get() { var message = string.Format("The current time on the server is: {0}", _watch.GetTime()); return message; } }

Actualmente estoy iniciando el objeto IWatch con Watch en el constructor WatchController. Quiero eliminar la dependencia de inicializar IWatch dentro del constructor usando el principio de inyección de dependencia de Windsor Castle.

¿Alguien puede proporcionarme los pasos para implementar la inyección de dependencia en este caso de WebApi? ¡Gracias por adelantado!



CodeCaster, Noctis y Cristiano le agradecen toda su ayuda y orientación. Acabo de recibir la solución para mi consulta anterior:

El primer paso es usar nuget para instalar los paquetes Windsor.Castle en la solución WebApi .

Considere el siguiente fragmento de código:

Interfaz IWatch.cs

public interface IWatch { DateTime GetTime(); }

Clase Watch.cs

public class Watch:IWatch { public DateTime GetTime() { return DateTime.Now; } }

El ApiController WatchController.cs se define de la siguiente manera:

public class WatchController : ApiController { private readonly IWatch _watch; public WatchController(IWatch watch) { _watch = watch; } public string Get() { var message = string.Format("The current time on the server is: {0}", _watch.GetTime()); return message; } }

En el controlador, hemos inyectado la dependencia a través del objeto IWatch en el constructor WatchController. He usado IDependencyResolver e IDependencyScope para lograr la inyección de dependencia en la API web. La interfaz IDependencyResolver se usa para resolver todo fuera de un ámbito de solicitud.

WindsorDependencyResolver.cs

internal sealed class WindsorDependencyResolver : IDependencyResolver { private readonly IWindsorContainer _container; public WindsorDependencyResolver(IWindsorContainer container) { if (container == null) { throw new ArgumentNullException("container"); } _container = container; } public object GetService(Type t) { return _container.Kernel.HasComponent(t) ? _container.Resolve(t) : null; } public IEnumerable<object> GetServices(Type t) { return _container.ResolveAll(t).Cast<object>().ToArray(); } public IDependencyScope BeginScope() { return new WindsorDependencyScope(_container); } public void Dispose() { } }

WindsorDependencyScope.cs

internal sealed class WindsorDependencyScope : IDependencyScope { private readonly IWindsorContainer _container; private readonly IDisposable _scope; public WindsorDependencyScope(IWindsorContainer container) { if (container == null) { throw new ArgumentNullException("container"); } _container = container; _scope = container.BeginScope(); } public object GetService(Type t) { return _container.Kernel.HasComponent(t) ? _container.Resolve(t) : null; } public IEnumerable<object> GetServices(Type t) { return _container.ResolveAll(t).Cast<object>().ToArray(); } public void Dispose() { _scope.Dispose(); } }

WatchInstaller.cs

Los instaladores son simplemente tipos que implementan la interfaz IWindsorInstaller . La interfaz tiene un único método llamado Install. El método obtiene una instancia del contenedor, que luego puede registrar componentes con la API de registro fluido:

public class WatchInstaller : IWindsorInstaller { public void Install(IWindsorContainer container, IConfigurationStore store) {

// Necesita registrar los controladores de forma explícita en su contenedor // Si no lo hace, recibirá una excepción:

Se produjo un error al intentar // crear un controlador de tipo ''xxxxController''. Asegúrese de que el controlador tenga un constructor público sin parámetros.

// Razón :: Básicamente, lo que sucedió es que no registraste tus controladores explícitamente en tu contenedor. Windsor intenta resolver tipos de concreto no registrados para usted, pero como no puede resolverlo (causado por un error en su configuración), devuelve nulo. Se lo fuerza a devolver nulo, porque la API web lo obliga a hacerlo debido al contrato IDependencyResolver. Como Windsor devuelve nulo, la API Web intentará crear el controlador en sí, pero como no tiene un constructor predeterminado lanzará la excepción "Asegúrese de que el controlador tenga un constructor público sin parámetros". Este mensaje de excepción es engañoso y no explica la causa real.

***container.Register(Classes.FromThisAssembly() .BasedOn<IHttpController>() .LifestylePerWebRequest());*** container.Register( Component.For<IWatch>().ImplementedBy<Watch>() ); } }

Finalmente, debemos reemplazar el resolvedor de dependencias predeterminado con la implementación de Windsor en Global.asax.cs (método Application_Start) e instalar nuestras dependencias:

private static IWindsorContainer _container; protected void Application_Start() { AreaRegistration.RegisterAllAreas(); WebApiConfig.Register(GlobalConfiguration.Configuration); FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters); RouteConfig.RegisterRoutes(RouteTable.Routes); BundleConfig.RegisterBundles(BundleTable.Bundles); ConfigureWindsor(GlobalConfiguration.Configuration); } public static void ConfigureWindsor(HttpConfiguration configuration) { _container = new WindsorContainer(); _container.Install(FromAssembly.This()); _container.Kernel.Resolver.AddSubResolver(new CollectionResolver(_container.Kernel, true)); var dependencyResolver = new WindsorDependencyResolver(_container); configuration.DependencyResolver = dependencyResolver; }