Azure Functions Serisi #11 – Dependency Injection

Merhaba,

Azure Functions yazı serisinin bu onbirinci makalesinde, bir Azure Function üzerinde Dependency Injection design pattern’ının nasıl kullanılabildiğini inceleyeceğiz.

Başlarken

Visual Studio editörü aracılığıyla bir Http Trigger türünden Azure Function oluşturunuz. Ardından Azure function üzerinde dependency injection yapmamızı sağlayacak olan Microsoft.Azure.Functions.Extensions kütüphanesini ilgili projeye yükleyiniz.
Azure Functions Serisi #11 - Dependency Injection

Kurulum&Entegrasyon

Hatırlarsanız eğer, klasik Asp.NET Core uygulamalarında bir servisin entegrasyonu için ‘Startup.cs’ dosyası kullanılmaktadır. İşte Azure function uygulamalarında da entegrasyon sorumluluğunu üstlenecek olan aynı mahiyette bir dosyaya ihtiyacımız vardır. Bunun için bir .cs uzantılı dosya ekleyerek adına yine ‘Startup’ diyebilir ve içeriğini aşağıdaki gibi inşa edebilirsiniz.

using Microsoft.Azure.Functions.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection;

[assembly: FunctionsStartup(typeof(ExampleFunction.Startup))]
namespace ExampleFunction
{
    public class Startup : FunctionsStartup
    {
        public override void Configure(IFunctionsHostBuilder builder)
        {
            builder.Services.AddSingleton<IMyService, MyService>();
        }
    }
}

Görüldüğü üzere, oluşturulan ‘Startup’ sınıfının ‘FunctionsStartup’ abstract class’ını implement etmesi gerekmekte ve override neticesinde uygulanan ‘Configure’ metodu içerisinde dependency injection servisine ilgili enjeksiyonlar gerçekleştirilmektedir. Ayriyetten ‘namespace’e odaklanırsanız eğer ‘assembly’ target’ı eşliğinde ‘FunctionsStartsup’ attribute’u ile işaretlenerek ‘Startup’ sınıfının verilmesi ile namespace seviyesinde bir bildirimde bulunulması gerekmektedir.

Dependency Injection Kullanımı

Oluşturulan ‘Startup’ class’ının, namespace seviyesinde ‘FunctionsStartup’ attribute’u ile işaretlenerek bildirilmesi neticesinde artık aynı namespace altında bulunan tüm functionlar için ilgili entegrasyonun sağlandığı anlamına gelmektedir. Haliyle bu aşamadan sonra herhangi bir function’da aşağıdaki gibi bir dependency injection talebinde bulunabilirsiniz.
Azure Functions Serisi #11 - Dependency Injection
Burada dikkat edilirse eğer constructor üzerinden dependency injection neticesinde elde edilen servise erişebilmek için hem class’ın hem de function’ın direkt olarak işaretli geldiği static keywordünün kaldırılması gerekmektedir.

Function Seviyesinde Dependency Injection Gerçekleştirme

Entekte edilmiş bağımlılıkları her daim constructor üzerinden talep etmek istemeyebilirsiniz. Bazen fonksiyon üzerinden de bu ihtiyacı gidermek daha efektif olabilecektir. Bunun için birçok yol/yordam mevcuttur, lakin bu yolların bir çoğu anti-patern olarak değerlendirilmektedir. Şimdi konuyu güzel bir yöntem olan Autofac kütüphanesiyle birlikte ele alalım.

Asp.NET Core uygulamalarında kullandığımız ‘FromServices’ attribute’u Azure Function’lar için geçerli değildir…

Function seviyesinde dependency injection talebinde bulunabilmek için AzureFunctions.Autofac kütüphanesinden faydalanacağız.
Azure Functions Serisi #11 - Dependency Injection

İlk olarak aşağıdaki gibi bir yapılandırma dosyası eklemeniz gerekmektedir.

      public class DIConfig
    {
        public DIConfig(string functionName)
        {
            DependencyInjection.Initialize(builder => builder.RegisterType<MyService>().As<IMyService>(), functionName);
        }
    }

Ardından aşağıdaki gibi function seviyesinde ilgili servisi enjekte edebilir, talebinizi yapabilirsiniz.

    [DependencyInjectionConfig(typeof(DIConfig))]
    static public class Function1
    {
        [FunctionName("Function1")]
        static public async Task<IActionResult> Run(
            [HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)] HttpRequest req,
            ILogger log, [Inject] IMyService myService)
        {
.
.
.

Burada ilgili function’ı ‘DependencyInjectionConfig’ attribute’u ile işaretleyerek yapılandırma dosyasını bildirmeniz ve ardından ‘Inject’ attribute’u ile servisi talep etmeniz yeterli olacaktır.

Options Pattern Kullanımı

Options pattern, Asp.NET Core mimarisinde ‘appsettings.json’ dosyasındaki verileri yapılandırılmış bir şekilde nesnel olarak bizlere sunan bir tasarım desenidir. Benzer mantıkla Azure function’da ise ‘local.settings.json’ dosyasındaki verileri yapılandırmamızı sağlamakta ve böylece sürece efektiflik kazandırmaktadır.

Tasarımın modellenmesi şu şekildedir;
‘local.settings.json’ dosyasında aşağıdaki gibi veri tanımlanır.

{
  "IsEncrypted": false,
  "Values": {
    "AzureWebJobsStorage": "UseDevelopmentStorage=true",
    "FUNCTIONS_WORKER_RUNTIME": "dotnet",
    "Datas": {
      "MyData": "Sende başını alıp gitme ne olur..."
    }
  }
}

Ardından bu veriye karşılık entity oluşturulur.

    public class Datas
    {
        public string MyData { get; set; }
    }

Ve ‘FunctionsStartup’ abstract class’ından türeyen ve bizimde ‘Startup’ ismini verdiğimiz class içerisinde aşağıdaki gibi ilgili veriler options pattern ile service provider’ına ilgili entity ile eşleştirilerek dahil edilir.

    public class Startup : FunctionsStartup
    {
        public override void Configure(IFunctionsHostBuilder builder)
        {
            builder.Services.AddSingleton<IMyService, MyService>();
            builder.Services.AddOptions<Datas>()
                .Configure<IConfiguration>((datas, configuration) =>
            {
                configuration.GetSection("Datas").Bind(datas);
            });
        }
    }

Burada ‘Bind’ operasyonunun işlevine değinirsek eğer; ‘Bind’, verilen section içerisindeki değerleri entity’de uygun property karşılıklarına bağlayan bir fonksiyondur.

Nihai olarak ilgili data ‘IOptions’ interface’i ile aşağıdaki gibi dependency injection ile talep edilir.

    public class Function1
    {
        readonly Datas _datas;
        public Function1(IOptions<Datas> datas)
        {
            _datas = datas.Value;
        }
.
.
.

İşte Azure Function üzerinde bu şekilde dependency injection gerçekleştirilmektedir 🙂

İlgilenenlerin faydalanması dileğiyle…
Sonraki yazılarımda görüşmek üzere…
İyi çalışmalar…

Bunlar da hoşunuza gidebilir...

1 Cevap

  1. 11 Ağustos 2020

    […] Azure Functions Serisi #11 – Dependency Injection […]

Bir cevap yazın

E-posta hesabınız yayımlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir

*