我需要创建一个实现 IActionModelConvention
和 IFilterFactory
的自定义操作过滤器。
我使用 IActionModelConvention
同时设置多个路由,我使用 IFilterFactory
注入(inject)一些我需要使用的服务。
问题 是IActionModelConvention
中的Apply()
方法在CreateInstance()
之前被调用> 来自 IFilterFactory
的方法,我需要注入(inject)的服务在 Apply()
中可用。
我的问题 是如何在调用 Apply()
方法之前注入(inject)服务?而且我也更喜欢使用 IFilterFactory
来注入(inject)服务,因为它不会强制我用 [ServiceFilter]
或 [TypeFilter]包装实际属性
属性。
这是我的代码:
public class Contains2RoutesAttribute : Attribute, IActionModelConvention, IFilterFactory
{
public ISomeService SomeService{ get; set; }
public IFilterMetadata CreateInstance(IServiceProvider serviceProvider)
{
ISomeService someService = serviceProvider.GetService<ISomeService>();
return new Contains2RoutesAttribute() { SomeService = someService };
}
public void Apply(ActionModel action)
{
// Here I need to use the service injected:
this.SomeService.DoSomething(); // ERROR: The service here is null.
action.Selectors.Clear();
// Adding route 1:
action.Selectors.Add(new SelectorModel
{
AttributeRouteModel = new AttributeRouteModel { Template = "~/index1" }
});
// Adding route 2:
action.Selectors.Add(new SelectorModel
{
AttributeRouteModel = new AttributeRouteModel { Template = "~/index2" }
});
}
}
最佳答案
您的 IActionModelConvention
实现只会在启动时运行一次。 Apply
将为每个操作调用一次。要在 Apply
函数内部使用 ISomeService
,请将其作为构造函数参数传递。您的 Contains2RoutesAttribute
类不必是 IFilterFactory
的属性或实现,因为您已在评论中确认它不参与 filter pipeline .这是一个代码示例,其中我还重命名了该类以更好地表示它在做什么(它不再是一个属性):
public class Contains2RoutesConvention : IActionModelConvention
{
private readonly ISomeService someService;
public Contains2RoutesConvention(ISomeService someService)
{
this.someService = someService;
}
public void Apply(ActionModel actionModel)
{
someService.DoSomething();
...
}
}
在 Startup.ConfigureServices
中注册此约定:
services.AddMvc(options =>
{
options.Conventions.Add(new Contains2RoutesConvention(new SomeService()));
});
这是它变得更有趣的地方。您不能将依赖注入(inject)与 convention 一起使用,所以在这个例子中,我在构造 Contains2RoutesConvention
时内联创建了一个 SomeService
的实例。如果你希望这个实例是一个可以在你的应用程序的其他地方使用的单例,你可以在 ConfigureServices
中做这样的事情:
var someService = new SomeService();
services.AddMvc(options =>
{
options.Conventions.Add(new Contains2RoutesConvention(someService));
});
services.AddSingleton<ISomeService>(someService);
当然,这取决于 SomeService
是否有自己的依赖项,但如果有,它们将无法从 DI 容器中解析,因为它在管道中还为时过早。
关于c# - Asp.net Core 自定义过滤器实现 IActionModelConvention 和 IFilterFactory,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53525645/