ASP.NET CoreのActionFilterとDI
8064 ワード
一、紹介
前のいくつかの文章はすべてASPについて話しています.NET Core MVCでの依存注入(DI)と拡張点の、ASP.NET COREのすべてのコンポーネントは注入に依存して拡張されており、IControllerActivatvatorのような機能点は、前の記事(参照.NET CoreソースコードがAutofacによって制御ローラ属性に依存することを実現していることを示す)でも言及されていますが、今日は主に似たような拡張点を紹介します.ASP.NET Core MVCでは,ActionFilters(すなわちフィルタ)への依存注入の拡張のための新しい機構を提供した.
二、フィルタ依存注入
ASP.NET Core MVCでは、フレームワークでIFIlterのタイプのAttributesを提供してActionを装飾し、Actionリクエストをブロックします.これは以前のバージョンではありましたが、依存注入と組み合わせて使用したい場合はIFIlterFactoryインタフェースを使用してActionFilterの作成プロセスを拡張します.
2.1 IFIlterFactoryインタフェース定義
public interface IFilterFactory : IFilter
{
IFilter CreateInstance([NotNull] IServiceProvider serviceProvider);
}
Filter Attributeを作成し、注入に依存する必要がある場合は、一般的に次のコードが必要です.public class FilterClass : ActionFilterAttribute
{
public FilterClass(IDependency1 dependency1, IDependency2 dependency2)
{
// ...use dependencies
}
}
ASP.NET Core MVCでは、ServiceFilterAttributeとTypeFilterAttributeの2つの簡単なIFIlterFactoryを提供しています.例を挙げて使い方を見てみましょう.public class HomeController: Controller
{
[TypeFilter(typeof(FilterClass))]
[ServiceFilter(typeof(FilterClass))]
public IActionResult Index()
{
return View();
}
}
2.2 ServiceFilterAttribute
実は名前を見て、一部の友达は考えることができて、それは依存注入のIFIlterFactoryに基づいて、Serviceという言葉はサービスを得ることによって依存注入を実現することを強化して、みんなは何を考えましたか?GetService()ですか?そうですね.実はそのメカニズムはこれです.
ServiceFilterを使用するには、依存注入容器に対応するタイプを登録する必要があります.例えば、次の例では、まずFilterClassタイプをIOC容器に登録します.public void ConfigureServices(IServiceCollection services)
{
services.AddSingleton();
services.AddMvc()
}
もちろんFilterClassタイプのコンストラクタに注入タイプが必要な場合もIOC容器に登録してから利用可能です.
ServiceFilterAttributeのソースコードを見てみましょう.public class ServiceFilterAttribute : Attribute, IFilterFactory, IOrderedFilter
{
public ServiceFilterAttribute([NotNull] Type type)
{
ServiceType = type;
}
public Type ServiceType { get; private set; }
public int Order { get; set; }
public IFilter CreateInstance([NotNull] IServiceProvider serviceProvider)
{
var service = serviceProvider.GetRequiredService(ServiceType);
var filter = service as IFilter;
if (filter == null)
{
throw new InvalidOperationException(Resources.FormatFilterFactoryAttribute_TypeMustImplementIFilter(
typeof(ServiceFilterAttribute).Name,
typeof(IFilter).Name));
}
return filter;
}
}
2.3 TypeFilterAttribute
もちろん、このServiceFilterのようなTypeFilterフィルタを使用することもできます.IFIlterFactoryインタフェースも実現し、依存注入を使用できるフィルタを作成することもできます.TypeFilterというのは、注入容器に依存してタイプを登録する必要がなく、フィルタを作成できるからです.コードを見てみましょう.public class TypeFilterAttribute : Attribute, IFilterFactory, IOrderedFilter
{
private ObjectFactory factory;
public TypeFilterAttribute([NotNull] Type type)
{
ImplementationType = type;
}
public object[] Arguments { get; set; }
public Type ImplementationType { get; private set; }
public int Order { get; set; }
public IFilter CreateInstance([NotNull] IServiceProvider serviceProvider)
{
if (this.factory == null)
{
var argumentTypes = Arguments?.Select(a => a.GetType())?.ToArray();
this.factory = ActivatorUtilities.CreateFactory(ImplementationType, argumentTypes ?? Type.EmptyTypes);
}
return (IFilter)this.factory(serviceProvider, Arguments);
}
}
三、結びの言葉
前の記事を読んだ友人は、ServiceProviderとActivatvatorUtilitiesの違いに気づいたと思いますが、本稿のServiceFilterAttributeとTypeFilterAttributeは原理的にもそれらによってFilterを作成しているので、シーンを使うのは皆さんの使い方次第です.実は最近見ます.NET Coreのソースコードは、インタフェースや工場が依存注入を使って拡張点を形成している例があちこちに見られますが、マイクロソフトは以前はコードの拡張点も多かったのですが、APIはそれほど開放的ではありません.ASP.NET Coreでは「オープン」なフレームワークを見ました.
GitHub:https://github.com/maxzhang1985/YOYOFxもし覚えていたら、スターの下で、一緒に交流することを歓迎します.
.NET Coreオープンソース学習群:214741894
ASP.NET Core MVCでは、フレームワークでIFIlterのタイプのAttributesを提供してActionを装飾し、Actionリクエストをブロックします.これは以前のバージョンではありましたが、依存注入と組み合わせて使用したい場合はIFIlterFactoryインタフェースを使用してActionFilterの作成プロセスを拡張します.
2.1 IFIlterFactoryインタフェース定義
public interface IFilterFactory : IFilter
{
IFilter CreateInstance([NotNull] IServiceProvider serviceProvider);
}
Filter Attributeを作成し、注入に依存する必要がある場合は、一般的に次のコードが必要です.
public class FilterClass : ActionFilterAttribute
{
public FilterClass(IDependency1 dependency1, IDependency2 dependency2)
{
// ...use dependencies
}
}
ASP.NET Core MVCでは、ServiceFilterAttributeとTypeFilterAttributeの2つの簡単なIFIlterFactoryを提供しています.例を挙げて使い方を見てみましょう.
public class HomeController: Controller
{
[TypeFilter(typeof(FilterClass))]
[ServiceFilter(typeof(FilterClass))]
public IActionResult Index()
{
return View();
}
}
2.2 ServiceFilterAttribute
実は名前を見て、一部の友达は考えることができて、それは依存注入のIFIlterFactoryに基づいて、Serviceという言葉はサービスを得ることによって依存注入を実現することを強化して、みんなは何を考えましたか?GetService()ですか?そうですね.実はそのメカニズムはこれです.
ServiceFilterを使用するには、依存注入容器に対応するタイプを登録する必要があります.例えば、次の例では、まずFilterClassタイプをIOC容器に登録します.
public void ConfigureServices(IServiceCollection services)
{
services.AddSingleton();
services.AddMvc()
}
もちろんFilterClassタイプのコンストラクタに注入タイプが必要な場合もIOC容器に登録してから利用可能です.
ServiceFilterAttributeのソースコードを見てみましょう.
public class ServiceFilterAttribute : Attribute, IFilterFactory, IOrderedFilter
{
public ServiceFilterAttribute([NotNull] Type type)
{
ServiceType = type;
}
public Type ServiceType { get; private set; }
public int Order { get; set; }
public IFilter CreateInstance([NotNull] IServiceProvider serviceProvider)
{
var service = serviceProvider.GetRequiredService(ServiceType);
var filter = service as IFilter;
if (filter == null)
{
throw new InvalidOperationException(Resources.FormatFilterFactoryAttribute_TypeMustImplementIFilter(
typeof(ServiceFilterAttribute).Name,
typeof(IFilter).Name));
}
return filter;
}
}
2.3 TypeFilterAttribute
もちろん、このServiceFilterのようなTypeFilterフィルタを使用することもできます.IFIlterFactoryインタフェースも実現し、依存注入を使用できるフィルタを作成することもできます.TypeFilterというのは、注入容器に依存してタイプを登録する必要がなく、フィルタを作成できるからです.コードを見てみましょう.
public class TypeFilterAttribute : Attribute, IFilterFactory, IOrderedFilter
{
private ObjectFactory factory;
public TypeFilterAttribute([NotNull] Type type)
{
ImplementationType = type;
}
public object[] Arguments { get; set; }
public Type ImplementationType { get; private set; }
public int Order { get; set; }
public IFilter CreateInstance([NotNull] IServiceProvider serviceProvider)
{
if (this.factory == null)
{
var argumentTypes = Arguments?.Select(a => a.GetType())?.ToArray();
this.factory = ActivatorUtilities.CreateFactory(ImplementationType, argumentTypes ?? Type.EmptyTypes);
}
return (IFilter)this.factory(serviceProvider, Arguments);
}
}