.NET [PL] Architecture Aurora Backend Get Noticed 2016 Issues

Konfiguracja Autofac w ASP.NET Core

Siema,

dziś krótki post dotyczący konfiguracji Autofac w ASP.NET Core. Co bardziej spostrzegawczy zauważyli, że otagowałem ten wpis jako „Problem”, a to dlatego, że na osiągnięcie pożądanego celu potrzebowałem jakieś… 3h? I jak to zwykle bywa przyczyną był brak jednej linijki, ale po kolei…

Pierwszą rzeczą jest dołączenie w naszym project.json zależności dla Autofaca. U mnie znalazł się on w każdym projekcie (warstwie). Wygląda to tak:

"Autofac.Extensions.DependencyInjection": "4.0.0-rc1-177",

Kiedy paczka się pobierze, możemy przystąpić do działania. Tutaj jednak należy się jeszcze małe słowo wyjaśnienia. W ASP.NET Core znajduje się już domyślny kontener, który rejestruje m.in UserManagera, RoleManagera, kontekst oraz serwisy do wysyłki mailów i sms-ów. Naszym celem będzie zatem:

  • przy pomocy kontenera domyślnego zarejestrowanie  UserManagera, RoleManagera, AuroraContext.
  • zarejestrowanie potrzebnych klas w każdej warstwie przy użyciu Autofac,
  • „przekazanie”  zarejestrowanych typów domyślnego kontenera do Autofacowego.
  • zbudowanie kontenera Autofacowego

No to po kolei. Jak powiedziałem domyślny kontener rejestruje już pewne klasy. Odbywa się to w klasie Startup w metodzie ConfigureServices. Ponieważ jednak nasz projekt jest rozbity na wiele warstw, musimy rejestrację przeprowadzić w warstwie DataAccess – stąd będzie widoczny zarówno kontekst, jak i menedżery ASP.NET Identity. W tym celu w każdym projekcie pojawił się folder DependencyInjection, który zawiera klasę statyczną AspNetRegistration. Klasa ta zawiera metodę Register, która przyjmuje IServiceCollection (tym rejestrujemy nasze zależności),a jej celem jest wywołanie Register z warstwy wyższej. Tym sposobem, nie dodając referencji „dojdziemy” do warstwy DataAccess. Przykładowa klasa wygląda tak:

public static class AspNetRegistration
{
        public static void Register(IServiceCollection services)
        {
            DataAccess.DependencyInjection.AspNetRegistration.Register(services);
        }
}

 

W warstwie DataAccess, możemy w końcu zarejestrować klasy ASP.NET Identity:

 

public static class AspNetRegistration
{
        public static void Register(IServiceCollection services)
        {
            services.AddIdentity<UserEntity,IdentityRole>(options =>
            {
                options.Password.RequireNonLetterOrDigit = false;
                options.Password.RequireUppercase = false;
 
            }).AddEntityFrameworkStores<AuroraContext>().AddDefaultTokenProviders();
        }
}

 

Metoda AddIdentity<TUser,TRole> rejestruje zarówno UserMangaera<TUser> jak i RoleManagera<TRole>. W naszym przypadku standardowego IdentityUsera zastąpimy UserEntity, który z niego dziedziczy (klasa ta jest opisana w poście o konfiguracji EF7, o tu), natomiast IdentityRole pozostaje domyślne. Dodam tylko, że to właśnie brak tej rejestracji powodował, że nie mogłem wstrzyknąć sobie UserManagera do serwisu (<facepalm_jaki_noob>) . Ok, kiedy nasze zależności zostały zarejestrowane, możemy przejść do samego Autofaca. ContainerBuildera tworzymy we wcześniej wspomnianej metodzie ConfigureServices w Startup. Od razu przedstawię Wam kod:

 

public IServiceProvider ConfigureServices(IServiceCollection services)
{
            // Add framework services.
            services.AddApplicationInsightsTelemetry(Configuration);
            AspNetRegistration.Register(services);
            services.AddMvc();
 
            var builder = new ContainerBuilder();
 
            builder.RegisterModule(new Registration());
            builder.Populate(services);Snippet</pre>
            var container = builder.Build();

            return container.Resolve<IServiceProvider>();      
}

 

Jak widać tworzymy najpierw buildera, który rejestruje moduł Autofac-owy. Zasada działania jest analogiczna do poprzedniej. W każdym projekcie w utworzonym folderze DependencyInjection znajduje się klasa Registration, która dziedziczy po Autofac-owej klasie Module. W przesłoniętej metodzie Load najpierw rejestrujemy moduł z warstwy wyższej, a następnie klasy z danej warstwy.  Przykładowo, w Domain wygląda to tak:

 

public class Registration : Module
{
        protected override void Load(ContainerBuilder builder)
        {
            builder.RegisterModule(new DataAccess.DependencyInjection.Registration());
 
            builder.RegisterGeneric(typeof (DomainDomainServiceFactory<>)).As(typeof (IDomainServiceFactory<>));
            builder.RegisterType<UserDomainService>().As<IUserDomainService>();
        }
}

 

Wracając do klasy Startup. Kiedy nasze klasy zostały zarejestrowane musimy dodać do tego menedżery zarejestrowane przez domyślny kontener. Dokonujemy tego metodą Populate, której podajemy services. Teraz jesteśmy gotowi do zbudowania naszego kontenera. Wykonujemy Build i gotowe 🙂 Teraz śmiało, możemy sobie wstrzykiwać nasze zależności.

 

Na dziś to wszystko. Generalnie jestem trochę do tyłu z planem, bo przez połowę weekendu użerałem się z Materialize CSS, którego coraz bardziej żałuję , no ale tak to jest, jak się nie umie SASS-a 😀 Jutro postaram się napisać o tym jak udało mi się wyseedować bazę w EF7, gdyż ostatnio podałem sposób na postawienie bazy z migracji. Po tej nieszczęsnej serii problemów ruszymy dalej z architekturą. To tyle, narazie !