Moduły Autofac – jak wykorzystać je do konfiguracji kontenera

Moduły Autofac?

Przy pracy z kontenerami Dependency Injection bardzo często dochodzi do sytuacji, gdy kod konfiguracji takiego kontenera bardzo się rozrasta. Dzieje się tak przede wszystkim wtedy, kiedy korzystamy z biblioteki, która nie wspiera autorejestracji (przez dłuższy czas w jednej z aplikacji WPF wykorzystywałem Unity, w którym trzeba było zarejestrować każdy typ ręcznie w kontenerze), przez co klasa konfiguracji może zawierać dziesiątki, jeśli nie setki linijek kodu. Na szczęście Autofac, którego wykorzystuję od dłuższego czasu w swoich projektach, wspiera autorejestrację oraz organizację rejestracji w formie małych klas (moduły Autofac), o których będzie mowa w tym wpisie.

Moduł Autofac jest prostą klasą, w której na ogół nadpisujemy metodę Load zawierającą konfigurację kontenera Autofac. Korzystając z modułów, możemy pogrupować rejestrację typów na mniejsze, logicznie powiązane z sobą elementy, aby późniejsze utrzymanie takich rejestracji było łatwiejsze.

Dodatkowo, gdy tworzymy rozbudowaną aplikację, którą dzielimy na jakieś części w formie modułów lub pluginów, możemy wykorzystać ten mechanizm, aby każdy taki element aplikacji zawierał rejestracje swoich własnych typów w kontenerze.

Darmowy kurs Visual Studio

Pracując z setkami programistów, zauważyłem, że większość osób nie pracuje efektywnie w Visual Studio. W skrajnych przypadkach korzystali z kopiowania z wykorzystaniem menu Edit. Wiem, że to dziwne, ale naprawdę niektórzy tak pracują. Dlatego postanowiłem stworzyć kurs Visual Studio – aby pomóc koleżankom i kolegom w efektywniejszej pracy.

Przygotowałem 30 lekcji e-mail, w których pokażę Ci, w jaki sposób pracować efektywniej i szybciej w Visual Studio. Poznasz dodatki, bez których nie wyobrażam sobie pracy w tym IDE.

Po więcej informacji zapraszam na dedykowaną stronę kursu: Darmowy Kurs Visual Studio.

Quiz C#

Ostatnio przygotowałem również quiz C#, w którym możesz sprawdzić swoją wiedzę. Podejmiesz wyzwanie?

Jak dodać moduły Autofac do aplikacji?

Na potrzeby dzisiejszego wpisu skorzystam z przykładu pochodzącego z wpisu o użyciu obiektów Lazy do wstrzykiwania zależności, w którym użyłem modułów Autofac do konfiguracji. Myślę, że najlepiej od razu przejść do kodu i zobaczyć, jakie moduły wykorzystałem w przykładzie:

public class DefaultModule : Module
{
protected override void Load(ContainerBuilder builder)
{
builder.RegisterAssemblyTypes(typeof(DefaultModule).Assembly)
.AsImplementedInterfaces()
.EnableInterfaceInterceptors()
.InterceptedBy(typeof(LoggerInterceptor));
}
}

DefaultModule to podstawowy moduł, który wykorzystuje autorejestrację do zarejestrowania wszystkich klas z aktualnego assembly pod ich interfejsami. Właściwie w każdej swojej aplikacji mam taki moduł, który jest odpowiedzialny za rejestrację większości typów w aplikacji. Dodatkowo w tej rejestracji dodaję jeszcze obsługę interceptora – ale to już temat na oddzielny wpis, który planuję dodać w najbliższym czasie.

public class ControllersModule : Module
{
protected override void Load(ContainerBuilder builder)
{
builder.RegisterControllers(typeof(AutofacConfig).Assembly);
}
}

ControllersModule jest odpowiedzialny za rejestrację kontrolerów ASP.NET MVC w kontenerze.

public class DataContextModule : Module
{
protected override void Load(ContainerBuilder builder)
{
builder.RegisterType<DataContext>()
.InstancePerRequest();
}
}

DataContextModule rejestruje obiekt kontekstowy Entity Framework w kontenerze, używając cyklu życia obiektu jeden per request http.

public class ValidatorsModule : Module
{
protected override void Load(ContainerBuilder builder)
{
builder.RegisterAssemblyTypes(typeof(ValidatorsModule).Assembly)
.Where(t => t.GetInterfaces().Contains(typeof(IValidator)))
.InstancePerRequest();
}
}

ValidatorsModule rejestruje walidatory FluentValidation w kontenerze. Ta rejestracja jest potrzebna, ponieważ w aplikacji walidatory wstrzykuje w formie konkretnego typu (często korzystam z różnych walidatorów dla tej samej klasy, w zależności od rodzaju akcji), a nie interfejsu, więc domyślna rejestracja z DefaultModule nie zarejestruje tych typów.

public class LoggerModule : Module
{
private static NLog.Logger _logger = NLog.LogManager.GetCurrentClassLogger();
protected override void Load(ContainerBuilder builder)
{
builder.RegisterInstance(new LoggerInterceptor());
}
protected override void AttachToComponentRegistration(IComponentRegistry componentRegistry,
IComponentRegistration registration)
{
registration.Activating += OnActivating;
base.AttachToComponentRegistration(componentRegistry, registration);
}
private void OnActivating(object sender, ActivatingEventArgs<object> e)
{
_logger.Info($"Activating: {e.Component.Activator.LimitType}");
}
}

LoggerModule jest specjalnym modułem przygotowanym na potrzeby tamtego przykładu. Służy on głównie do logowania informacji o tworzonych obiektach przez kontener, co było przydatne podczas przykładu z obiektami Lazy. Przy okazji pokazuję, że w module nie tylko musimy rejestrować typy w kontenerze, ale możemy zrobić też inne rzeczy.

Mając już przygotowane moduły, należy jeszcze skonfigurować kontener, aby z nich skorzystał. Robi się to bardzo prosto:

public class AutofacConfig
{
public static IContainer Configure()
{
var builder = new ContainerBuilder();
builder.RegisterAssemblyModules(typeof(AutofacConfig).Assembly);
var container = builder.Build();
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
return container;
}
}

Całą pracę wykonuje metoda RegisterAssemblyModules, do której przekazujemy assembly, z którego chcemy załadować moduły. Przykład zbudowany jest z tylko jednego projektu, dlatego wywołują metodę tylko raz.

Podsumowanie

Jak widać, skorzystanie z modułów Autofac powoduje, że kod konfigurujący kontener jest dużo lepiej zorganizowany. Lepiej się go utrzymuje, a znalezienie konkretnej konfiguracji jest łatwiejsze.

Nie zapomnij pobrać przykładu z githuba i sprawdzić, jak działają moduły w praktyce.

1 thought on “Moduły Autofac – jak wykorzystać je do konfiguracji kontenera

Dodaj komentarz

Twój adres e-mail nie zostanie opublikowany.