در مورد فیلترهای سراسری، حلقهی زیر در کلاس StructureMapFilterProvider فراخوانی نخواهد شد:
بنابراین container.BuildUp ایی هم بر روی فیلتر در حال اجرا، فراخوانی نمیشود و وابستگیهای آن تامین نخواهند شد.
برای حل این مشکل، بجای روش معمول معرفی فیلترهای سراسری:
بنویسید:
در این حالت، در ابتدای کار برنامه، تمام وابستگیهای مرتبط با LogAttribute هم وهله سازی میشوند.
مشکل!
این وهله سازی، فقط یکبار آن هم در ابتدای برنامه انجام میشود. یعنی وابستگیهای استفاده شدهی در فیلتر سراسری، صرفنظر از طول عمر تعریف شدهی برای آنها توسط IoC Container، دیگر وهله سازی مجدد نخواهند شد و این مساله برای حالتهایی مانند کار با دیتابیس مشکل ساز است.
برای حل این مشکل، اینترفیس IContainer را به فیلتر تزریق کنید:
در این حالت هرچند کلاس LogAttribute ایی که به صورت فیلتر سراسری تعریف شدهاست، یکبار در آغاز کار برنامه وهله سازی میشود، اما وابستگیهای مورد نیاز آن، توسط container.GetInstance به ازای هر بار فراخوانی، مجددا ساخته خواهند شد و دیگر تک وهلهای نخواهند بود.
روش بهتر transient کردن وابستگیها: استفاده از Func
var filters = base.GetFilters(controllerContext, actionDescriptor); foreach (var filter in filters)
برای حل این مشکل، بجای روش معمول معرفی فیلترهای سراسری:
GlobalFilters.Filters.Add(new LogAttribute());
GlobalFilters.Filters.Add(SmObjectFactory.Container.GetInstance<LogAttribute>());
مشکل!
این وهله سازی، فقط یکبار آن هم در ابتدای برنامه انجام میشود. یعنی وابستگیهای استفاده شدهی در فیلتر سراسری، صرفنظر از طول عمر تعریف شدهی برای آنها توسط IoC Container، دیگر وهله سازی مجدد نخواهند شد و این مساله برای حالتهایی مانند کار با دیتابیس مشکل ساز است.
برای حل این مشکل، اینترفیس IContainer را به فیلتر تزریق کنید:
public class LogAttribute : ActionFilterAttribute { private readonly IContainer _container; //نباید به این صورت تعریف شود چون در فیلترهای سراسری فقط یکبار وهله سازی خواهد شد //public ILogActionService LogActionService { get; set; } public LogAttribute(IContainer container) { _container = container; } public override void OnActionExecuted(ActionExecutedContext filterContext) { _container.GetInstance<ILogActionService>().Log("......data......"); //LogActionService.Log("......data......"); base.OnActionExecuted(filterContext); } }
روش بهتر transient کردن وابستگیها: استفاده از Func