2011-10-21 10 views
16

así que he quedado atascado mientras que intenta conseguir mi servicio web ASMX de usar la inyección de dependencia y el uso de una COI para hacerlo. Quiero que mi servicio web pueda usar mis servicios internos de la capa empresarial. El servicio web debe ser utilizado por un cliente externo de un dominio diferente y se usará principalmente para enviar y recibir información sobre entidades tales como Pedidos y Clientes.ASMX inyección de dependencia y de la COI

Un ejemplo sería:

public class MyService : System.Web.Services.WebService 
{ 
    [WebMethod] 
    public string HelloWorld() 
    { 
     return new MyBusinessService().MyMethod(); 
    } 
} 

public class MyBusinessService : IMyBusinessService 
{ 
    public string MyMethod() 
    { 
     return "hello"; 
    } 
} 

Quiero usar la inyección de dependencias para eliminar la necesidad de "Newing" Conectar el servicio, pero no puedo encontrar una manera de hacer esto. Puedo hacer que funcione con personas pobres, o al menos creo que se llama "pobres".

así:

public class MyService : System.Web.Services.WebService 
{ 
    private IMyBusinessService _myService; 

    public MyService(IMyBusinessService myService) 
    { 
     _myService = myService; 
    } 

    public MyService() : this(new MyBusinessServie()) { } 

    [WebMethod] 
    public string HelloWorld() 
    { 
     return _myService.MyMethod(); 
    } 
} 

Pero yo simplemente no puede conseguir mi cabeza alrededor de cómo utilizar un contenedor IoC para inyectar mis dependencias porque no puedo conseguir el servicio para funcionar sin un constructor sin parámetros. Tenga cuidado, no soy un programador experimentado y recién comencé a probar la inyección de dependencias y conseguí que funcionara bien en mi aplicación de formularios de Windows con structuremap, pero me quedé atascado en esta.

Respuesta

33

Desafortunadamente no hay ninguna manera por uno realizar la inyección de constructor con los servicios web en ASP.NET. Es un requisito de ASP.NET que proporcione un constructor predeterminado. El constructor de MyService es lo más parecido a la raíz de composición que puede obtener con este tipo de servicio web, sin usar un contenedor DI.

Con ASP.NET no es raro tener múltiples raíces composición. Que pueden ser los constructores de los servicios web individuales y las páginas web. Si está utilizando ASP.NET MVC, es ControllerFactory, que es más compatible con DI.

Con la implementación de la parte importante no es mover la construcción del gráfico de objetos del servicio web, ya que esta es la raíz de su composición. Lo más importante es mantener el servicio web lo más delgado posible, mantener la mayor parte de la lógica en la dependencia para que pueda ser probado o reutilizado. Sacar información de los encabezados HTTP es un ejemplo de una tarea que el servicio web podría hacer pasar esa información a la dependencia.

Un buen libro para referirse a patrones y técnicas de DI es Dependency Injection in .NET por Mark Seemann.

Si el servicio web implementado System.Web.IHttpHandler en lugar de derivados de System.Web.Services.WebService se podía poner en práctica su DI de este modo:

Global.ashx.cs

public class Global : HttpApplication 
{ 
    protected void Application_PreRequestHandlerExecute(object sender, EventArgs e) 
    { 
     var context = ((HttpApplication)sender).Context; 

     var needsMyBusinessService = context.Handler as INeedMyBusinessService; 
     if (needsMyBusinessService != null) 
      needsMyBusinessService.MyBusinessService = new MyBusinessService(); 
    } 
} 

MyService.ashx.cs

public class MyService : IHttpHandler, INeedMyBusinessService 
{ 
    public IMyBusinessService MyBusinessService { get; set; } 

    public bool IsReusable { get { return true; } } 

    public void ProcessRequest(HttpContext context) 
    { 
     // uses my dependency 
    } 
} 

INeedMyBusinessService.cs

public interface INeedMyBusinessService 
{ 
    IMyBusinessService MyBusinessService { get; set; } 
} 

Sin embargo la captura con esta aplicación es que es hace no trabajo con los servicios web que implementan System.Web.Services.WebService como el objeto de servicio web no está inicializado hasta después del evento PreRequestHandlerExecute es llamada, que es el último evento antes de ProcessRequest se llama.

El ejemplo anterior funciona si desea tener una instancia única para cada servicio web. Si desea tener la misma instancia (ciclo de vida de Singleton) de MyBusinessService para cada solicitud de servicio web, puede implementar el archivo Global.ashx.cs como lo siguiente:

public class Global : HttpApplication 
{ 
    private static IMyBusinessService businessService; 

    protected void Application_Start(object sender, EventArgs e) 
    { 
     Global.businessService = new MyBusinessService(); 
    } 

    protected void Application_PreRequestHandlerExecute(object sender, EventArgs e) 
    { 
     var context = ((HttpApplication)sender).Context; 

     var needsMyBusinessService = context.Handler as INeedMyBusinessService; 
     if (needsMyBusinessService != null) 
      needsMyBusinessService.MyBusinessService = Global.businessService; 
    } 
} 
Cuestiones relacionadas