Содержание
В предыдущей части мы вкратце познакомились с Dependency Injection в ASP.NET и даже смогли на простейшем примере посмотреть как регистрируются сервисы в контейнере DI и используются приложением. Сегодня разберемся подробнее с разработкой собственных сервисов в ASP.NET Core
Пример сервиса
Пусть, например, нам необходимо получать от пользователя в запросе какую-либо строку и формировать на её основе различные хэши (MD5, SHA256 и т.д.). Используя сведения из предыдущей части, мы можем написать следующий код сервиса ASP.NET Core:
public interface IHashCalculator { public string GetHash(string data); } public class MD5Hash : IHashCalculator { public string GetHash(string data) { return Convert.ToHexString(MD5.HashData(Encoding.ASCII.GetBytes(data))); } } public class SHA256Hash : IHashCalculator { public string GetHash(string data) { return Convert.ToHexString(SHA256.HashData(Encoding.ASCII.GetBytes(data))); } }
У интерфейса IHashCalculator
определен метод GetHash
, который на основании строки data
формирует хэш. Конкретные реализации этого интерфейса — два класса: MD5Hash
и SHA256Hash
. Теперь мы можем добавить IHashCalculator
в список сервисов приложения и использовать этот сервис:
public class Program { public static void Main(string[] args) { var builder = WebApplication.CreateBuilder(args); builder.Services.AddTransient<IHashCalculator, MD5Hash>(); //регистрируем сервис var app = builder.Build(); app.Run(async context => { var svc = app.Services.GetService<IHashCalculator>();//получаем сервис var request = context.Request; var data = request.Query["data"].ToString(); if (string.IsNullOrEmpty(data)) await context.Response.WriteAsync("Empty data"); else { await context.Response.WriteAsync($"HASH: {svc?.GetHash(data)}"); } }); app.Run(); }
Здесь мы зарегистрировали сервис в контейнере DI перед построением приложения и, затем получили его в middleware. При этом строка data
отправляется пользователем через параметры запроса. Работающее приложение будет выглядеть следующим образом:
Так как ASP.NET Core сопоставила IHashCalculator
с конкретной реализацией интерфейса — MD5Hash
при регистрации сервиса, то в результате мы получаем MD5-хэш. Можем поменять реализацию интерфейса и получить хэш SHA-256:
builder.Services.AddTransient<IHashCalculator, SHA256Hash>(); //регистрируем сервис
Сервис без реализации интерфейса
ASP.NET Core позволяет регистрировать конкретные классы как сервисы. Например, мы можем создать такой класс:
public class Hash { public string GetMD5(string data) { return Convert.ToHexString(MD5.HashData(Encoding.ASCII.GetBytes(data))); } public string GetSHA256(string data) { return Convert.ToHexString(SHA256.HashData(Encoding.ASCII.GetBytes(data))); } }
затем, зарегистрировать его в контейнере DI следующим образом:
builder.Services.AddTransient<Hash>(); //регистрируем сервис
и использовать конкретный класс как сервис:
app.Run(async context => { var svc = app.Services.GetService<Hash>();//получаем сервис var request = context.Request; var data = request.Query["data"].ToString(); if (string.IsNullOrEmpty(data)) await context.Response.WriteAsync("Empty data"); else { await context.Response.WriteAsync($"MD5: {svc?.GetMD5(data)} \r\n"); await context.Response.WriteAsync($"SHA-256: {svc?.GetSHA256(data)}"); } });
Создание методов расширения для регистрации сервисов
Как мы уже знаем, для регистрации сервисов могут использоваться методы расширения IServiceCollection
, которые имеют общую структуру имени Add[имя_сервиса]
. Мы также можем создавать свои методы расширения для регистрации своих сервисов, например:
public static class ServiceProviderExtensions { public static void AddHash(this IServiceCollection services) { services.AddTransient<Hash>(); } }
и затем использовать этот метод расширения для регистрации сервиса:
//builder.Services.AddTransient<Hash>(); builder.Services.AddHash();
Результат работы приложение будет точно таким же, как и в предыдущем примере.
Итого
Сегодня мы подробнее разобрались с тем, как создавать и регистрировать свои сервисы в ASP.NET Core. При этом, в качестве сервиса может выступать конкретный класс без реализации какого-либо интерфейса. Также научились создавать методы расширения для регистрации сервисов в контейнере DI.