atributlar-praktikada--odeme-terminali-yigiriq

Atributlar praktikada: Ödəmə terminalı yığırıq

        Atributlar .NET platformasında marker rolunu oynayırlar. Məhz onların istifadəsi ilə artıq  biznes prosesləri başqa dillərdə olduğu kimi yox, aspekt yönümlü yazmaq mümkün olur. Atributlar Aspektyönümlu proqramlaşdırmanın ən uğurlu praktikalarından biridir.  

               Bu məqaləmizdə və qarşıdakı bir neçə məqaləmizdə Atributları praktiki formada təsvir etməyə çalışacağıq. Atributlar metaverilənlərə əlavə məlumat yazırlar. Həmin məlumatları daha sonra refleksiya ilə oxuyaraq proqramda məntiq(logic) formalaşdırmaq, bununla da bir sıra əməliyyatlar yerinə yetirmək olur. Atributlarla bağlı yadda saxlamalı olduğumuz şeylərdən biri onun refleksiya ilə işləməsidir. .NET platformasında validasiya, avtorizasiya, autentifikasiya, rol sistemi, kontraktların müəyyənləşdirilməsi vəs.  kimi prosesləri atributlar vasitəsilə etmək olur. Keçən dərslərimizdən birində interfeys və refleksiya tətbiq edərək dinamik provider sistemi hazırlamışdıq(link burada) . Həmin sistemi yenidən yazaraq bu dəfə interfeys əvəzinə atributlar istifadə edəcəyik.

               Texniki tapşırığımız təsviri belədir: Şirkətimiz üçün ödəmə terminalı hazırlamaq lazımdır. Həmin ödəmə terminalının əsas kod strukturu artıq yazılıb. Yeni provayderlər əlavə edildikcə əsas kod strukturunda heç bir dəyişiklik etmədən provayderləri dinamik şəkildə application-a əlavə edə bilməliyik. Yəni yeni provayder yazıldıqda girib əsas proqramın kodunda dəyişiklik etməməliyik. Provayderlərin hər biri .dll formatında olacaq və yazıldıqdan sonra özəl bir qovluğa( bizim nümunədə libs qovluğu) yerləşdiriləcək. Proqram həmin qovluqdan bu dll-ləri oxumalı və ekrandə hər bir dll-ə uyğun provayder formalaşdırmalıdır.

               Əvvəlcə yeni bir solution formalaşdıraraq orada 4 proyekt yaradırıq. Proyektin 1-i WinForm(MainApplicationUI), digər 3-ü isə dll(class library) olacaq.(Proyekti burada yükləyə bilərsiniz.)

               Bütün proqram məntiqi ProviderProtocol dll-i üzərində cəmlənəcək .Həmin dll-ə digər bütün proyektlər link(reference) saxlamalıdır. Burada Əsas proqram (MainApplicationUI) ilə provayderlərin(AzercellProject, MegaSigortaProject) əlaqə saxlama kontraktı atributlar vasitəsilə verilib.

               ProviderProtocol dll-i özündə 2 atribut saxlayır. ProviderNameAttribute ilə hər bir provayderin adını göstərəcəyik, ProviderOperationAttribute isə qrafiki interfeysdə baş verəcək hadisəni və onun realizasiyasını saxlayır.

ProviderNameAttribute-u hər bir provayderin üzərinə yazaraq həmin provayderin Uİ-da hansı adla görünəcəyini göstəririk.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;


namespace ProviderProtocol
{
    [AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
   public sealed class ProviderNameAttribute : Attribute
    {
        public string ProviderName { get; private set; }
        public ProviderNameAttribute(string providerName)
        {
            ProviderName = providerName;
        }

    }
}

ProviderOperationAttribute ilə hər provayderə klik və ya double click olunduqda hansı işin baş vercəyini göstəririk. Əməliyyatın növü üçün də ayrica bir enum yaratmışıq.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ProviderProtocol
{
    public enum EventType
    {
        Click,
        DblClick,
        MouseMove
    }

    [AttributeUsage(AttributeTargets.Method, Inherited = false, AllowMultiple = false)]
   public sealed class ProviderOperationAttribute : Attribute
    {
       public EventType EventType { get; private set; }
        // This is a positional argument
        public ProviderOperationAttribute(EventType eventType)
        {
            EventType = eventType;
        }
    }
}

AzercellProject-in içərisindəki kod çox sadədir. Burada klasımızı sadəcə lazımi atributlarla mark etmişik.

using ProviderProtocol;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;


namespace AzercellProject
{
    [ProviderName("Azercell")]
    public class AzercellProvider
    {
        [ProviderOperation(EventType.Click)]
        public void OnButtonClicked()
        {
            //implementation simplified for learning..
            MessageBox.Show("This is Azercell provider");
        }
    }
}

Mega Sigorta proyekti də eyni formadadır. Məqsəd sadəcə əməliyyatı emulyasiya etməkdir. Şablon hazır olduqdan sonra artıq daha qəlibz biznes proseslər yaza bilərsiniz.

using ProviderProtocol;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace AzercellProject
{
    [ProviderName("MegaSigorta")]
    public class MegaSigortaProvider
    {
        [ProviderOperation(EventType.Click)]
        public void OnButtonClicked()
        {
            //implementation simplified for learning..
            MessageBox.Show("This is Mega Sigorta provider");
        }
    }
}

(Proyekti burada yükləyə bilərsiniz.)

               Dll-lərimiz hazır olduqdan sonra ümumi proyekti build edirik və alınan dll-ləri MainApplicationUİ proyektində libs qovluğuna atırıq.

MainApplicationUİ isə libs qovluğundakı bütün dll-ləri oxuyaraq onlara refkelsiya tətbiq edir. Həmin dll-lərin içərisindəki klasların və onların metodlarının ProviderNameAttributeProviderOperationAttribute atributlarını realizə edib etmədiyini yoxlayır. Əgər klas ProviderNameAttribute atributunu realizə edibsə həmin adda interfeysdə bir düymə yaradır. Əgər klasın hər hansı bir metodu ProviderOperationAttribute atributunu realizə edibsə ozaman həmin metodu müvafiq hadisəyə bağlayıb işə salır.

namespace MainApplicationUI
{
    public partial class MainForm : Form
    {
        ProviderVisualizer _providerVisualizer;
        public MainForm()
        {
            InitializeComponent();
            _providerVisualizer = new ProviderVisualizer(grbx_providers);
        }


        private void MainForm_Load(object sender, EventArgs e)
        {
            //get path to libs folder
            string libsPath = ApplicationPath.PathTo("libs");
            _providerVisualizer.LoadFrom(libsPath);
        }
    }
}

Göründüyü kimi əsas proseslər ProviderVisualizer klasında cəmlənib .Həmin klasın daxili koduna baxaq. ProviderVisualizerin əsas işi dll-ləri tapıb provayder şəkildə onları sistemə əlavə etməkdən ibarətdir.

namespace MainApplicationUI.Core
{
   public class ProviderVisualizer
    {
        private readonly Control _control;
        private int _locationX ;
        private int _locationY ;


        public ProviderVisualizer(Control control)
        {
            _control = control;
            InitializeDefaultParams();
        }


        public void ClearProviders()
        {
            _control.Controls.Clear();
            InitializeDefaultParams();
        }


        private void InitializeDefaultParams()
        {
            _locationX = 20;
            _locationY = 34;
        }


        public void AddProvider(string providerName,Action operation,EventType eventType)
        {
            Button button = new Button
            {
                Text = providerName,
                Size = new Size(150, 100),
                Location = new Point(_locationX, _locationY)
            };
            if(eventType == EventType.Click)
            {
                button.Click += (sndr, args) =>
                {
                    operation();
                };
            }
            else
                if(eventType == EventType.DblClick)
            {
                button.DoubleClick += (sndr, args) =>
                {
                    operation();
                };
            }
           
            _locationX += 150;
            _control.Controls.Add(button);
        }


        public void LoadFrom(string path)
        {
            //get path to libs folder
            string libsPath = path;
            //get only dll files
            string[] providers = Directory.GetFiles(libsPath, "*.dll");


            //for simplicity excaped LINQ query...
            //for every provider ....
            foreach (string provider in providers)
            {
                //load it into application RAM..
                Assembly assembly = Assembly.LoadFile(provider);


                //get all types in assembly
                Type[] assemblyTypes = assembly.GetTypes();


                foreach (Type assemblyType in assemblyTypes)
                {

                     //get provider name
                    ProviderNameAttribute providerNameAttr = (ProviderNameAttribute)assemblyType.GetCustomAttribute(typeof(ProviderNameAttribute));
                   
                     // get the method 
                    var method = assemblyType.GetMethods()
                                          .Where(x => x.GetCustomAttribute(typeof(ProviderOperationAttribute)) != null)
                                               .FirstOrDefault();

                    //if provider name and method exist
                    if (providerNameAttr != null && method != null)
                    {  
                        //create object of the class
                      object instance = Activator.CreateInstance(assemblyType);

                       //provider operation for eventType
                       var providerOperationAttr = method.GetCustomAttribute < ProviderOperationAttribute >();

                        this.AddProvider(providerNameAttr.ProviderName, () =>
                         {
                             method.Invoke(instance, null);
                         }, providerOperationAttr.EventType);
                    }
                }
            }
        }
    }
}

Artıq proyekti build etdikdən sonra hər iki provayderi əsas proqramın libs qovluğunu atırıq və proqramı işə saldıqda hər iki provayderin Uİ-da göründüyünün şahidi oluruq.



Tural

Tural Süleymani

Süleymani Tural Microsoft-un MCSD statuslu mütəxəssisidir, 2008-ci ildən bu yana proqramlaşdırma üzrə tədris aparır

Müəllifin bu dildə ən son postları

Bu yazıları da bəyənə bilərsiniz