PictOgr - pierwszy kod

21.03.2017

Zmiana biblioteki logów

Już na samym począteczku problemy, musiałem wymienić bibliotekę logów z log4net na NLog, okazało się, iż w moim projekcie opartym na .NET 4.5.2 nie można wykorzystać biblioteki log4net i tyle z nauki.

Oczywiście, żeby było śmieszniej dowiedziałem się o tym po konfiguracji, instalacji w sytuacji wystąpienia problemu z zapisem logów, czyli X czasu poszło się paść.

Autofac - kontenerek na moje śmieci

Autofac Kolejno przyszedł czas na wdrożenie DIP (Dependency Inversion Principle) przy wykorzystaniu Dependency Injection. Do tego po instalacji pakietu trzeba trochę popracować nad szkieletem wykorzystującym Autofac-a.

A czym jest taki kontenerek? To bardzo proste, to składowisko obiektów naszej aplikacji. Trzeba go załadować w sposób jaki się chcę. A potem już tylko korzystać.

Realizuje fragment zasad SOLID, a dokładnie ostatnią literkę.

Zasada DIP określa, iż obiekty nie powinny być tworzone na żądanie, a wstrzykiwane z zewnątrz. Dzięki czemu zależność obiektu wykorzystującego inne klasy jest odwrócona. Określamy jakie klasy/interfejsy chcemy otrzymać, a kontener je dostarczy.

Dobra rada dla programisty - bądź SOLIDny.

Poniżej klasa statyczna implementująca ładowanie modułów kontenera.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
using System.Linq;
using Autofac;
using Autofac.Core;

namespace PictOgr.Core.AutoFac
{
    public static class Container
    {
        public static ContainerBuilder CreateBuilder()
        {
            var builder = new ContainerBuilder();

            LoadModules(builder);

            return builder;
        }

        private static void LoadModules(ContainerBuilder builder)
        {
            var types = AppDomain.CurrentDomain.GetAssemblies()
                .SelectMany(x => x.GetTypes())
                .Where(t => 
                    t.IsAssignableTo() 
                    && t.IsClass 
                    && !t.IsAbstract);

            foreach (var type in types)
            {
                builder.RegisterModule((IModule) Activator.CreateInstance(type));
            }
        }
    }
}

PictOgr - pierwszy kod Kontener można ładować parami, nie trzeba używać jednej łopaty. Można dodawać wiele ładując je automatycznie, za to odpowiedzialny jest zaznaczony fragment kodu.

Polega to na przeszukaniu wszystkich klas w aplikacji i wyciągnięciu ich typów spełniających wskazane warunki.

Ładowanie moich śmieci

Z kolei kod poniżej to modulik, mały jest i w tym przypadku ładuje wszystkie zależności dla NLoga. Po wykonaniu tego kodu w programie można wstrzykiwać loggera.

Oczywiście można rejestrować w kontenerze dowolne klasy np. builder.RegisterType<SplashScreenView>();

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
using Autofac;
using Autofac.Extras.NLog;

namespace PictOgr.Core
{
    public class CoreModule : Module
    {
        protected override void Load(ContainerBuilder builder)
        {
            base.Load(builder);
			
            builder.RegisterModule();
        }
    }
}

Moduły tworzymy zazwyczaj w obszarach powiązanych razem z klasami jakie są ładowane. Unikamy tym samym zwalenia tworzenie wszystkich obiektów w jednym miejscu, czyli porządeczek.

Używanie kontenera

Po załadowaniu fajnie byłoby użyć Autofaca, ale wiadomo wszystko ma swój początek i koniec, dlatego należy zainicjować kontener. W moim przypadku będzie to w głównej klasie App.

L.12 tworzy kontener, czyli ładuje wszystkie moduliki z PictOgr-a.

Linia niżej to wyciągnięcie obiektu z kontenera, w tym przypadku okna powitalnego SplashScreenView.

Rejestrowanie obiektów w kontenerze, przy starcie aplikacji.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
using System.Windows;
using Autofac;
using PictOgr.Core.AutoFac;
using PictOgr.SplashScreen.Views;

namespace PictOgr
{
	public partial class App : Application
	{
		private void OnStartup(object sender, StartupEventArgs e)
		{
			var container = Container.CreateBuilder().Build();

			var splashScreenView = container.Resolve();

			splashScreenView.Show();
		}
	}
}

Dependency Injection

Jednak w tym przypadku żądamy od kontenera konkretnego obiektu, nie różni się to za bardzo od klasycznego podejścia, czyli new Klasa(), dlatego DI wykonywać będziemy w następujący sposób:

Wstrzykiwanie zależności.

1
2
3
4
5
6
7
8
9
public class StartApplicationCommand : ICommand
{
		private readonly MainWindowView mainWindowView;

		public StartApplicationCommand(MainWindowView mainWindowView)
		{
			this.mainWindowView = mainWindowView;
		}
        ...

Dotyczy to klasy MainWindowView, nigdzie nie jest ona tutaj tworzona, jest otrzymywana jako atrybut konstruktora, biblioteka Autofac wstrzykuje tą zależność.

Ogromne możliwości

Autofac jest bardzo rozbudowaną biblioteką, pozwala w różny sposób tworzyć obiekty, zbudowany jest na bazie wzorca projektowego Fluent Interface, który to pozwala na kaskadowe wywoływanie metod z klasy macierzystej. Każda metoda zwraca referencję do klasy, tym samym bazujemy na jednej klasie i wykonujemy na niej operacje.

Zastosowanie fluenta daje możliwość zapisu kolejnych etapów rejestrowania klasy z wykorzystaniem separacji kropką.

builder.RegisterType<TestClass>().As<ITestClass>();

W powyższym przykładzie rejestrujemy klase TestClass jako interfejs ITestClass.

PictOgr - pierwszy kod

Możemy także określić, iż klasa ma mieć tylko jedną instancję (Wzorzec Singleton) poprzez dopisanie

builder.RegisterType<TestClass>().As<ITestClass>().SingleInstance();

Można zarejestrować klasę samodzielnie ją tworząc, taką operację wykonujemy poniższym poleceniem:

builder.RegisterInstance(new TestClass()).As<ITestClass>();

Poniższy kodzik pokazuje, że można wykonać metodę w tworzonym obiekcie zaraz po jej utworzeniu.

builder.RegisterType<TestClass>().As<ITestClass>().OnActivated(e => e.Instance.Test());

Teraz to już pozostaje tylko „wstrzykiwać”… zależności 😉

Na dzisiaj tyle. Jestem w implementacji testów i CQRSa.

Liczę na konstruktywne komentarze:).


Daj Się Poznać 2017

Jest to post przygotowany na potrzeby konkursu „Daj Się Poznać 2017” organizowanym przez Macieja Aniserowicza.

Blog https://mrdev.pl
Projekt https://mrdev.pl/pictogr-pomysl
GitHub github.com/krzysztofowsiany/pictogr
Snapchat www.snapchat.com/add/gocom7
Facebook www.facebook.com/PictOgr-1729700930654225
Twitter twitter.com/gemu_gocom
RSS http://mrdev.pl/category/daj-sie-poznac-2017/feed

Zapisz się na listę :)