Подтвердить что ты не робот

Инъекция зависимостей ASMX и IoC

Итак, я застрял, пытаясь заставить мой asmx webservice использовать инъекцию зависимостей и использовать IoC для этого. Я хочу, чтобы мой веб-сервис мог использовать мои внутренние службы бизнес-уровня. Веб-сервис должен использоваться внешним клиентом из другого домена и в основном будет использоваться для отправки и получения информации о таких объектах, как Заказы и Клиенты.

Пример:

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

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

Я хочу использовать инъекцию зависимостей, чтобы избавиться от необходимости "обновлять" мою службу, но я не могу найти способ сделать это. Я могу заставить его работать, используя бедных мужчин DI, или, по крайней мере, я думаю, что это называется "бедные мужчины".

вот так:

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();
    }
}

Но я просто не могу понять, как использовать контейнер IoC для ввода моих зависимостей, потому что я не могу заставить службу работать без конструктора без параметров. Пожалуйста, будьте любезны, я не опытный программист и только что начал тестировать инъекцию зависимостей и получил его, чтобы нормально работать на моем приложении форм Windows с помощью структуры структуры, но застрял на этом.

4b9b3361

Ответ 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;
    }
}