5

我正在尝试实现我的自定义授权属性,例如:

 public class MyCustomAuth : AuthorizeAttribute
{
    private readonly IUserService _userService;

    public MyCustomAuth(IUserService userService)
    {
        _userService= userService;
    }
... continued
 }

我正在使用 Castle Windsor 来自动解决依赖关系。

当我尝试将它用作操作方法的属性时,显然我被要求传递参数,或者我需要一个无参数的构造函数,它应该以某种方式解决它的依赖关系。

我尝试使用属性注入依赖项,但 Windsor 没有注入它。

我现在看到的唯一选择是手动实例化具体对象依赖项,从而失去 Windsor 的好处。

你将如何解决这个问题?

4

3 回答 3

8

您不能将 DI 与属性一起使用——它们是元数据;

public class MyCustomAuth : AuthorizeAttribute
{
    public void OnAuthorization(...)
    {
         IUserService userService = ServiceLocator.Current.GetInstance<IUserService>();
    }
}

在此处了解 Windsor/ServiceLocator 。

在这里看到类似的问题。

于 2009-11-06T19:14:26.173 回答
3

您可以使用自定义 ControllerActionInvoker 并注入属性依赖项(您不能进行构造函数注入,因为框架会处理属性的实例化)。你可以看到我刚刚写的关于这种技术的博客文章。

于 2009-11-06T20:01:30.483 回答
1

您没有提供任何城堡代码或配置示例。因此,我假设您是城堡的新手并且不熟悉注册过程。

首先,您想要操作的任何对象都必须通过注册类型来自 Castle Windsor。话虽如此,您尝试将城堡温莎与属性一起使用会走错路 - 因为属性没有在代码中引用,而是被反映在上面。因此,没有地方供 IoC(在这种情况下为温莎城堡)创建对象。

我这么说是因为你试图完成的事情已经通过不同的方式完成了。首先,将依赖注入放在控制器上。

public class PostController
{
  private IUserService _userService;
  public PostController (IUserService userService)
  {
    _userService = userService;
  }

  // other logic

}

要让 Castle 工作,您必须注册所有类型。因此,您必须在 Castle Windsor 中注册 IUserService,以及哪些服务实现了该接口。您可以通过在 global.asax 中使用 container.AddComponentWithLifeStyle 的手动过程来执行此操作;或者更优选的方法是使用配置文件。

使用配置文件,您的 IUserService 将如下所示:

<?xml version="1.0" encoding="utf-8" ?>
<castle>
    <components>
        <!--lifestyle="singleton|thread|transient|pooled|webrequest|custom"-->

        <component
            id="UserService"
            service="MyMvcProject.IUserService, MyMvcProject"
            type="MyMvcProject.UserService, MyMvcProject"
            lifestyle="transient">
        </component>
    </components>
</castle>

MyMvcProject 是您的项目的名称,并确保使用确切的名称空间和接口的完全限定名称以及类型。请提供您实际命名空间的代码示例,否则我们无法为您提供任何进一步的帮助。

在此之前,您需要修改 app.config 或 web.config 以注册 Castle Windsor 的 searchGroup:

<configSections>

    <section name="castle" 
        type="Castle.Windsor.Configuration.AppDomain.CastleSectionHandler, Castle.Windsor"/>

</configSections>

<castle configSource="castle.config"/>

现在您已全部注册和设置,是时候告诉您的 MVC 应用程序“使用 Castle Windsor 创建我的控制器的每个实例”。这样做意味着 Castle Windsor 作为一个控制反转(又名 IoC)容器,将检查控制器的依赖关系并查看它是否依赖于 IUserService 并实现 UserService 的实例。Castle 将查看其注册类型的配置,并查看您已为 IUserService 注册了服务。并且,它将在您的配置文件中看到您要实现实现 IUserService 的具体 UserService 类。因此,当请求对 IUserService 的依赖时,IoC 容器将返回 UserService。

但在此之前,您必须告诉您的 MVC 应用程序使用您配置的 IoC 容器。您可以通过注册一个新的 ControllerFactory 来做到这一点。为此,请参阅我对这个问题的回答:

为什么 Castle Windsor 试图将我的“内容”和“脚本”文件夹解析为控制器?

并注意如何注册该代码的 global.asax 部分。它工作得很好!

现在,当所有这些都说完之后,您想要授权用户。使用实现表单身份验证的普通 [Authorize],并使用您的 _userService 获取登录用户的任何用户详细信息。

于 2009-11-06T18:59:57.827 回答