我正在尝试实现我的自定义授权属性,例如:
public class MyCustomAuth : AuthorizeAttribute
{
private readonly IUserService _userService;
public MyCustomAuth(IUserService userService)
{
_userService= userService;
}
... continued
}
我正在使用温莎城堡自动解决依赖关系。
当我尝试将它用作操作方法的属性时,显然我被要求传递参数,或者我需要一个无参数构造函数来以某种方式解析它的依赖关系。
我尝试用属性注入依赖项,但 Windsor 没有注入它。
我现在看到的唯一选择是手动实例化具体对象依赖关系,从而失去 Windsor 的优势。
你会如何解决这个问题?
I'm trying to implement my custom authorize attribute like:
public class MyCustomAuth : AuthorizeAttribute
{
private readonly IUserService _userService;
public MyCustomAuth(IUserService userService)
{
_userService= userService;
}
... continued
}
I am using Castle Windsor for automatically resolve the dependency.
When I try to use it as an attribute of an action method obviously I am asked to pass the parameter or I need to have a parameter-less constructor that should resolve in some way it's dependency.
I tried to inject the dependency with a property but Windsor is not injecting it.
The only option I see now would be to instantiate manually the concrete object dependency loosing the benefit of Windsor.
How would you solve this problem?
发布评论
评论(3)
您不能将 DI 与属性一起使用 - 它们是元数据;
此处了解 Windsor/ServiceLocator。
查看类似的问题 这里。
You cannot use DI with attributes - they're metadata;
Learn about Windsor/ServiceLocator here.
See similar question here.
您可以使用自定义 ControllerActionInvoker 并注入属性依赖项(您无法进行构造函数注入,因为框架处理属性的实例化)。您可以看到 我刚刚发表的有关此技术的博客文章。
You can use a custom ControllerActionInvoker and inject property dependencies (you can't do constructor injection because the framework handles instantiation of attributes). You can see a blog post I just did on this technique.
您没有提供任何城堡代码或配置示例。因此,我假设您是城堡新手,并且不熟悉注册过程。
首先,您想要操作的任何对象都必须通过注册类型来自温莎城堡。话虽如此,尝试将温莎城堡与属性一起使用时您会走上错误的道路 - 因为属性不是在代码中引用,而是被反映。因此,IoC(本例中为温莎城堡)没有地方创建对象。
我这样说是因为你想要完成的事情已经通过不同的方式完成了。首先,将依赖注入放在控制器上。
为了让 Castle 工作,您必须注册所有类型。因此,您必须在温莎城堡内注册 IUserService 以及哪些服务实现该接口。您可以通过在 global.asax 中使用 container.AddComponentWithLifeStyle; 进行手动处理来完成此操作;或者更优选的方法是使用配置文件。
使用配置文件,您的 IUserService 将如下所示:
MyMvcProject 是您的项目的名称,并确保使用准确的命名空间和接口的完全限定名称以及类型。请提供您实际命名空间的代码示例,否则我们无法为您提供进一步帮助。
在此之前,您需要修改 app.config 或 web.config 以注册 Castle Windsor 的 searchGroup:
现在您已全部注册并设置完毕,是时候告诉您的 MVC 应用程序“使用 Castle Windsor 创建我的控制器的每个实例。”这样做意味着 Castle Windsor 作为控制反转(又名 IoC)容器,将检查控制器的依赖关系,并发现它依赖于 IUserService 并实现 UserService 的实例 。 Castle 将查看其注册类型的配置,并查看您是否已为 IUserService 注册了服务。并且,它会在您的配置文件中看到您想要实现实现 IUserService 的 UserService 具体类。因此,当请求对 IUserService 的依赖时,IoC 容器将返回 UserService。
但在此之前,您必须告诉您的 MVC 应用程序使用您配置的 IoC 容器。您可以通过注册一个新的 ControllerFactory 来完成此操作。为此,请参阅我在这个问题上的回答:
为什么 Castle Windsor 试图将我的“Content”和“Scripts”文件夹解析为控制器?
并注意如何注册该文件夹的 global.asax 部分代码。效果很好!
现在,当所有这些都说完并完成后,您想要授权用户。使用实现表单身份验证的普通 [Authorize],并使用 _userService 获取登录用户的任何用户详细信息。
You did not supply any castle code or configuration examples. Therefore, I am assuming you are new to castle and unfimilar with the registration process.
First of all, any object you want to act upon must come from Castle Windsor via a registered type. With that said, you are going down the wrong path by trying to use castle windsor with attributes - because attributes are not referenced in code, but instead are reflected upon. Therefore, there is not a place for IoC (Castle Windsor in this case) to create the object.
I say this, because what you are trying to accomplish has already been done via different means. First of all, put your dependency injection on your controllers.
For Castle to work, you have register all types. So, you have to register IUserService, and what services implement that interface, within Castle Windsor. You can do this via a manual process in your global.asax with container.AddComponentWithLifeStyle; or the more preferred method is to use a configuration file.
Using a configuration file, your IUserService would look something like this:
MyMvcProject is the name of your project and make sure to use the exact namespace and fully qualified name of the interface, and type. Please give code samples of your actual namespaces, else we cannot help you any further.
Before that will work, you will need to modify your app.config or web.config to register the searchGroup for Castle Windsor:
Now that you are all registered and setup, it is time to tell your MVC application to "Use Castle Windsor to create each instance of my Controllers." Doing this means that Castle Windsor, being an Inversion-of-Control (aka IoC) container, will inspect the dependencies of your controller and see that it depends on IUserService and implement an instance of UserService. Castle will look into its configuration of registered types and see that you have registered a service for IUserService. And, it will see in your configuration file that you want to implement the concrete class of UserService that implements IUserService. So, the IoC container will return UserService when a dependency on IUserService is requested.
But before that can happen, you have to tell your MVC application to use your configuired IoC container. You do this by registering a new ControllerFactory. To do that, see my answer over at this question:
Why is Castle Windsor trying to resolve my 'Content' and 'Scripts' folder as a controller?
And notice the global.asax part of how to register that code. It works quite well!
Now, when all of that is said and done, you want to authorize a user. Use the normal [Authorize] that implements Forms Authentication, and use your _userService to grab any user details of the signed in user.