C# 如何将方法参数插入自定义属性

C# 如何将方法参数插入自定义属性,c#,custom-attributes,C#,Custom Attributes,我有一个名为authorizeAttribute的自定义属性,其构造函数如下所示: public AuthoriseAttribute(int userId) { .. blah } [Authorise(????????)] public UserDetailsDto GetUserDetails(int userId) { .. blah } 这与名为GetUserDetails()的方法一起使用,如下所示: public AuthoriseAttribute(int userI

我有一个名为authorizeAttribute的自定义属性,其构造函数如下所示:

public AuthoriseAttribute(int userId)
{
  .. blah
}
[Authorise(????????)]
public UserDetailsDto GetUserDetails(int userId)
{
  .. blah
}
这与名为
GetUserDetails()
的方法一起使用,如下所示:

public AuthoriseAttribute(int userId)
{
  .. blah
}
[Authorise(????????)]
public UserDetailsDto GetUserDetails(int userId)
{
  .. blah
}
在运行时,authorize属性的存在会导致执行一些需要用户ID的授权代码。显然,这可以从
GetUserDetails()
方法的参数中提取,但这意味着授权代码取决于给定特定名称的方法参数

我希望能够将
userId
参数的实际值传递到属性中,以便授权代码与传递到属性(即,不是方法参数)的值一起工作,该属性的名称是已知的

类似这样的东西(不起作用):


这样的事情可能吗?

让vcsjones的评论成为答案,这是不可能的

属性是元数据;它们在编译时编译到程序集中,在运行时不会更改。因此,传递到属性中的任何参数都必须是常量;文本、常量变量、编译器定义等

一种可行的方法是将属性设置为AOP元素,使用类似PostSharp的框架,或者使用Unity框架等滚动您自己的框架。这将允许您通过使用属性装饰将“拦截器”附加到方法,然后,它将在属性中运行代码,并且还将确切了解如何调用该方法,包括参数值。查看此博客:

在ASP.NET MVC中,有一种方法可以通过操作方法(通常不使用属性)实现此功能


我可以通过以下方法解决这个问题:

public class AuthorizeAttribute
{
    protected bool RequireIdClaim { get; private set; }

    public AuthorizeAttribute(bool requireIdClaim = false)
    {
        RequireIdClaim = requireIdClaim;
    }

    public Authorize() 
    {
        //regular auth stuff here

        if (RequireIdClaim)
        {
            var routeData = context.ActionContext.Request.GetRouteData();
            var requiredIdClaim = Convert.ToInt32(routeData.Values["id"]); 

            //Check here if their user profile has a claim to that Id
        }
    }
}
然后是要检查ID的具体方法

[HttpGet]
[Route("{id}")]
[Authorize(requireIdClaim: true)]
public UserDetailsDto GetUserDetails(int userId)
{
    .. blah
}
如果你不想检查他们的身份,只想确认他们的身份

[HttpGet]
[Route("")]
[Authorize]
public bool isLoggedIn()
{
    .. blah
}
当然,您可以按照自己的喜好组织授权过程,但这种想法允许您在auth过程中获取它们的ID,因为它是作为路由数据传入的。
更多信息:

可能是因为这是一篇老文章,但现在这是可能的

[MyAttribute(MyAttributeVar= "myMethodVar")]
public void MyMethod(int myMethodVar)

不,不可能。属性是元数据。参数值必须是常量。有一点我不明白-为什么要授权方法参数?IMO-您可能需要授权方法的调用方-这是否正确?您所描述的不能直接完成,我相信编译器错误告诉您。了解“authorize属性的存在导致某些授权代码执行”是如何工作的将很有帮助。您应该能够让那里的代码查看userId参数。您可以让属性通过其他方式(如WCF上下文或Active Directory)获取用户信息,而不是将用户信息传递给每个方法。。。那么你的方法是干净的,没有多重责任。谢谢大家@蒂姆:我在用温莎城堡拦截。属性的存在会导致拦截方法调用,并允许我在调用之前运行代码。我可以访问方法信息和属性信息。我需要获取用户ID(以及其他内容,但我保持问题的简单性),但是没有简单的方法告诉拦截器在哪里找到用户ID。它可能会作为名为
userId
的int参数传递给方法,或者它可能被深埋在某个复杂的类型参数中。你偷了vcsjones的答案,我会为此奖励你!我有AOP的东西,并运行;我的问题是告诉拦截器中的代码在哪里找到运行授权逻辑所需的数据,因为该属性可能用于用不同的签名装饰多个方法。我不会说这是偷窃+1感谢您接受我的评论并将其转化为有用的答案。您可能会通过将要用作字符串的参数名提供给它来提供此信息:
[Authorize(“userId”)]
。当您定义的拦截器运行时,它应该能够检查有关触发它的方法调用的元数据,并且应该能够找到具有指定名称的参数,并将其值赋予基于此属性应运行的任何代码。谢谢。是的,我考虑过了。如果参数是复杂类型,我不确定如何使其工作。我必须定义某种神奇的语法,将所需数据的位置表示为字符串。需要考虑一下。您不想定义
[Authorize(“userId.SomeProp”)]
。如果需要知道参数的确切类型,也可以指定:
[Authorize(“userId”,typeof(MyComplexType))]