Vyzkoušejte IoC kontejner AutoFac
Tento článek byl napsán v roce 2015. Vývojářské technologie se neustále inovují a článek již nemusí popisovat aktuální stav technologie, ideální řešení a můj současný pohled na dané téma.
Přestože jsem více než 2 roky pracoval s Castle Windsor, poslední dobou mi stále častěji pod rukama probíhá kontejner AutoFac. V tomto článku shrnu vybrané vlastnosti a možnosti nastavení.
Dokumentace
Dlouhou dobu jsem upřednostňoval Castle Windsor, který má sice mizernou dokumentaci ale na druhou stranu i silnou komunitu, která zajišťuje dobrou podporu na Stack Overflow. AutoFac má velmi podrobnou dokumentaci a celkem srozumitelné nastavení všeho, co může vývojář potřebovat. Z technického hlediska nemá už moc smysl IoC kontejnery srovnávat, protože se liší jen použitím a případně rychlostí. Ta je stejně jako i Windsor Castle velmi dobrá.
Podpora frameworků a komponent
AutoFac nabízí možnost integrace do MVC (až do verze 5), Web API 2, OWIN, WCF nebo například Web Forms. Nechybí podpora řady komponent, jako časostroj Quartz.NET nebo logovací nástroje NLog / Log4Net.
Install-Package Autofac Install-Package Autofac.Mvc5 Install-Package Autofac.WebApi2
Konfigurace MVC 5
Konfigurace probíhá stejně jako v případě všech kontejnerů v global.asax.cs
v metodě Application_Start()
.
protected void Application_Start() { var builder = new ContainerBuilder(); // Register your MVC controllers. builder.RegisterControllers(typeof(MvcApplication).Assembly); // OPTIONAL: Register model binders that require DI. builder.RegisterModelBinders(Assembly.GetExecutingAssembly()); builder.RegisterModelBinderProvider(); // OPTIONAL: Register web abstractions like HttpContextBase. builder.RegisterModule<AutofacWebTypesModule>(); // OPTIONAL: Enable property injection in view pages. builder.RegisterSource(new ViewRegistrationSource()); // OPTIONAL: Enable property injection into action filters. builder.RegisterFilterProvider(); // Set the dependency resolver to be Autofac. var container = builder.Build(); DependencyResolver.SetResolver(new AutofacDependencyResolver(container)); }
Nastavení je samozřejmě vhodnější provést v samostatných třídách, než je přímo vypisovat v Application_Start()
.
AutoFac má speciální modul, který umí zaregistrovat řadu webových abstraktních tříd, např.: HttpRequestBase
, RequestContext
nebo užitečný UrlHelper
.
Property Injection
Trochu přes ruku je s AutoFac řešena property injection. Zatímco například v Ninjectu stačí uvést nad property datovou anotaci [Inject]
, v AutoFac je nutná konfigurace.
builder.RegisterType<MyService>().As<IService>().PropertiesAutowired();
Teprve pro takto registrované komponenty je možné aplikovat property injection.
Scanování assemblies a hromadná registrace
Typický požadavek na IoC kontejner je hromadná registrace (repositářů, services apod.)
var assembly = Assembly.GetExecutingAssembly(); builder.RegisterAssemblyTypes(assembly) .Where(t => t.Name.EndsWith("Repository")) .Except<ExtraRepository>() .AsImplementedInterfaces();
Lifetime
Další častý požadavek je možnost nastavení životnosti instancí. V případě webových aplikací je často používaná InstancePerRequest
:
builder.RegisterType<MyContext>() .As<IDbContext>() .WithParameter("connectionString", "MyConnectioStringName") .InstancePerRequest();
Dále jsou dostupné InstancePerDependency
(ve Windsoru Transient
), která vytváří unikátní instance pro každý request dané služby nebo například SingleInstance
(jinak Singleton
) aj.
Property Injection pro filter atributy
V MVC aplikacích se nedá obejít bez vytváření různých action filtrů. V těch je často potřeba sáhnout na repositář nebo na službu (kvůli logování, ověřování uživatele aj.). V případě AutoFac stačí přidat konfiguraci:
builder.RegisterFilterProvider();
a následně je možné vytvářet snadno různé vlastní atributy:
public class LogFilter : ActionFilterAttribute { public ILogger Logger { get; set; } public override void OnActionExecuting(ActionExecutingContext filterContext) { Logger.Log("Executing!"); } }
nebo zmíněné autorizační atributy:
public class AuthAttribute : AuthorizeAttribute { public IUserRepository UserRepository { get; set; } protected override bool AuthorizeCore(HttpContextBase httpContext) { // logic here return true; } }
Logování
Přímo v dokumentaci AutoFac je popsána integrace log4net, nicméně na nuget.org se už dají najít integrační moduly pro většinu běžně používaných logovacích frameworků.
Install-Package log4net.AutoFac Install-Package Autofac.Extras.NLog
Závěr
Přestože jsem se už na Castle Windsor zvykl, pomalu začínám přecházet na AutoFac. Nabízí v podstatě všechno, co potřebuji a je mnohem lépe dokumentovaný. Příjemná je i syntaxe a neustále rostoucí komunita vývojářů, kteří vytváří různá extra rozšíření a jsou ochotni na Stack Overflow řešit specifické problémy.