Ответ 1
К сожалению, нет никакого способа выполнить инжектор конструктора с веб-службами в ASP.NET. Это требование ASP.NET, которое вы предоставляете конструктор по умолчанию. Конструктор MyService близок к корню композиции, который вы можете получить с помощью этого типа веб-сервиса, без использования контейнера DI.
В ASP.NET нет ничего необычного, чтобы иметь несколько корней композиций. Какими могут быть конструкторы отдельных веб-сервисов и веб-страниц. Если вы используете ASP.NET MVC, это ControllerFactory, более дружественный к DI.
В вашей реализации важной частью является не перемещение конструкции графа объектов из веб-службы, так как это ваш корневой каталог. Главное, чтобы сделать веб-сервис как можно более тонким, сохранить большую часть логики в зависимости, чтобы ее можно было протестировать или использовать повторно. Извлечение информации из заголовков HTTP является примером задачи, которую веб-служба могла бы затем передать этой информации в зависимости.
Хорошая книга для ссылок на шаблоны и методы DI - это Инъекция зависимостей в .NET от Mark Seemann.
Если ваш веб-сервис реализовал System.Web.IHttpHandler
вместо получения System.Web.Services.WebService
, вы могли бы реализовать свой DI так:
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; }
}
Однако улов с этой реализацией заключается в том, что не работает с веб-службами, которые реализуют System.Web.Services.WebService
, поскольку объект веб-службы не инициализируется до тех пор, пока событие PreRequestHandlerExecute
не будет вызвано, вызывается последнее событие до ProcessRequest
.
Приведенный выше пример работает, если вы хотите иметь уникальный экземпляр для каждой веб-службы. Если вы хотите иметь один и тот же экземпляр (жизненный цикл Singleton) MyBusinessService
для каждого запроса веб-службы, вы можете реализовать файл Global.ashx.cs следующим образом:
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;
}
}