HandleErrorAttribute
拡張する習慣がありますFilterAttribute
。
Unity がコントローラーの依存関係自体を注入すると同時に、この属性に依存関係を注入するにはどうすればよいですか?
HandleErrorAttribute
拡張する習慣がありますFilterAttribute
。
Unity がコントローラーの依存関係自体を注入すると同時に、この属性に依存関係を注入するにはどうすればよいですか?
わかりました、それを理解しました。
ほとんどの場合、私は彼が指摘したブログ投稿から上記のベンのソリューションを使用しました。
問題は、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
上記の内容とは異なり、ForEachループ内でビルドアップを実行しても問題が発生することはありませんでした。また、System.Typeと既存のオブジェクトを受け取るBuildUpメソッドの他のオーバーロードのいずれかを使用することで、インターフェイスを介してオブジェクトを参照するだけであるという元の問題を克服しました。
上記のすべてが完了すると、依存性をフィルターに直接注入できるようになります。
コメントや考えは大歓迎です。
乾杯マイク
2 つのオプションがあります
最初のオプションは、カスタム ActionInvoker を作成することです。これは、思ったほど難しくありません。このブログ投稿をチェックしてください。具体的には NInject を扱っていますが、Unity はプロパティ インジェクションをサポートしているため、Unity を使用するように例を変更できます。
これは、IoC コンテナーを結合するオプションであり、お勧めしません。
public class MyFilter
{
IMyService MyService {get; set;}
MyFilter() : MyFilter(MyUnityContainer.Resolve<IMyService>())
{ }
MyFilter(IMyService service)
{
MyService = service;
}
}