私はカスタム FilterAttribute
を持っています。MVC/Unity - カスタムFilterAttributesに依存関係を挿入する方法は?
どのようにして、コントローラの依存関係自体を注入するのと同時にこの属性に依存性を注入することができますか?
私はカスタム FilterAttribute
を持っています。MVC/Unity - カスタムFilterAttributesに依存関係を挿入する方法は?
どのようにして、コントローラの依存関係自体を注入するのと同時にこの属性に依存性を注入することができますか?
あなたは最初のオプションは、ほぼ同じハードそれが聞こえるようではないカスタムActionInvokerを、書くために2つのオプション
を持っています。このblog postをチェックしてください。具体的にはNInjectを扱いますが、Unityはプロパティインジェクションをサポートしていますので、Unityを使用するようにサンプルを変更することができます。
これはIoCコンテナを結合するオプションであり、推奨されません。
public class MyFilter
{
IMyService MyService {get; set;}
MyFilter() : MyFilter(MyUnityContainer.Resolve<IMyService>())
{ }
MyFilter(IMyService service)
{
MyService = service;
}
}
わかりました。
私は主に、彼が指摘したブログの投稿からBenのソリューションを使用しました。
問題は、Unityが少し違って動作することです。
フィルタがIActionFilterおよびIExceptionFilterタイプであるため、フィルタに直接依存関係を挿入することはできません。これは私に彼らが読んでいたと信じさせました。そうではありません。 Unityが注入するためには明示的な型を知る必要があるだけです。
したがって、記事で提供されているオーバーライドされたメソッドでは、Unityユーザは対象のタイプのフィルタにクエリを実行し、それらを構築する必要があります。オーバーライドされたメソッドで
public UnityActionInvoker(IUnityContainer container, IList<Type> typesToInject)
{
_container = container;
_typesToInject = typesToInject;
}
そして、このような何か:
var needsInjection = filters.Where(filter => typesToInject.Contains(filter.GetType()));
少し厄介を、それが一度だけ行われる必要がある、とベンが示唆するように切り離され、すべてを保持します。
もう1つは、フィルタがそのコンテキストで読み込み専用であるため、foreachループ内で_container.BuildUp(filter)を呼び出すことができないことです。
私もこの問題に遭遇し、現在は有効な解決策があります。これは上記のソリューションと似ていますが、若干の違いがあり、完全なUnityコードも追加されています。
最初に私は上記の理由でプロパティインジェクションを使用します。上記のように、UnityでBuildUpメソッドを使用して、すでに作成されたフィルタにプロパティを注入します。
これを行うには、私のすべてのコントローラに新しいカスタムベースクラスを継承させる必要があります。その基本クラスで、自分のカスタムActionInvokerを設定するためにCreateActionInvokerメソッドをオーバーライドします。
Protected Overrides Function CreateActionInvoker() As System.Web.Mvc.IActionInvoker
Return CustomActionInvoker
End Function
私のCustomActionInvokerでは、私はGetFiltersメソッドをオーバーライドします。
Protected Overrides Function GetFilters(ByVal controllerContext As ControllerContext, ByVal actionDescriptor As ActionDescriptor) As FilterInfo
Dim info = MyBase.GetFilters(controllerContext, actionDescriptor)
For Each MyAuthorizationFilter In info.AuthorizationFilters
MvcApplication.Container.BuildUp(MyAuthorizationFilter.GetType, MyAuthorizationFilter)
Next
For Each MyActionFilter In info.ActionFilters
MvcApplication.Container.BuildUp(MyActionFilter.GetType, MyActionFilter)
Next
For Each MyResultFilter In info.ResultFilters
MvcApplication.Container.BuildUp(MyResultFilter.GetType, MyResultFilter)
Next
For Each MyExceptionFilter In info.ExceptionFilters
MvcApplication.Container.BuildUp(MyExceptionFilter.GetType, MyExceptionFilter)
Next
Return info
End Function
上記とは逆に、For Eachループの内部にビルドアップを行うと問題が発生していることがわかりませんでした。私はまた、System.Typeと既存のオブジェクトを取るBuildUpメソッドの他のオーバーロードの1つを使用して、インターフェイスを介して参照されるオブジェクトのみを持つという元の問題を克服しました。
私は今すべてのフィルタに依存関係を注入することができます。
ご意見やご感想をいただきありがとうございます。
乾杯マイク
私は誰かのコードが間違っている、どこか別のブログ記事で見つかったソリューションを試みたが、UnityとNinjectの間にいくつかの違いがあるようです、または:)。 フィルタは、オーバーライドされた "InvokeExceptionFilters"に到達するまでに読み取り専用です。 新しいフィルタを宣言して依存関係を挿入することはできますが、指定したExceptionFiltersのリストに依存関係を注入しようとすると何も起こりません。 新しいフィルタを作成してベースクラスに渡すことができましたが、属性自体に提供されている宣言的な情報をすべて失います。 –