简体   繁体   English

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

[英]How to plug method parameters into custom attribute

I have a custom Attribute called AuthoriseAttribute whose constructor looks like this:我有一个名为 AuthoriseAttribute 的自定义属性,其构造函数如下所示:

public AuthoriseAttribute(int userId)
{
  .. blah
}

This is used with a method called GetUserDetails() like this:这与名为GetUserDetails()的方法一起使用,如下所示:

[Authorise(????????)]
public UserDetailsDto GetUserDetails(int userId)
{
  .. blah
}

At runtime, the presence of the Authorise attribute causes some authorisation code to execute which requires the ID of the user.在运行时,Authorize 属性的存在会导致执行一些需要用户 ID 的授权代码。 Obviously, this can be extracted from the parameter of the GetUserDetails() method, but this means that the authorisation code depends on the method's parameter being given a particular name.显然,这可以从GetUserDetails()方法的参数中提取,但这意味着授权代码取决于方法的参数被赋予特定名称。

I would like to be able to pass in the actual value of the userId parameter into the attribute, so that the authorisation code works with the value passed in to the attribute (ie not the method parameter), whose name is known.我希望能够将userId参数的实际值传递到属性中,以便授权代码与传递给名称已知的属性(即不是方法参数)的值一起使用。

Something like this (which doesn't work):像这样的东西(不起作用):

[Authorise(userId)]
public UserDetailsDto GetUserDetails(int userId)
{
  .. blah
}

Is such a thing possible?这样的事情可能吗?

There is a way to do this _in ASP.NET MVC_ with action-methods (not with attributes in general)一种方法与动作的方法(不是一般的属性)做到这一点_in ASP.NET MVC_

public class CustomAttribute : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        int userId = (int)filterContext.ActionParameters["userId"];
    }
}

Making vcsjones' comment an answer, this is not possible.使 vcsjones 的评论成为答案,这是不可能的。

Attributes are metadata;属性是元数据; they are compiled into the assembly at compile-time and do not change during runtime.它们在编译时被编译到程序集中并且在运行时不会改变。 As such, any parameters you pass into an attribute must be constants;因此,您传递给属性的任何参数都必须是常量; literals, constant variables, compiler defines, etc.文字、常量变量、编译器定义等。

The one way this would work is to make the attribute an AOP element, using a framework like PostSharp or rolling your own with the Unity Framework etc. This would allow you to attach an "interceptor" to the method by decorating it with an attribute, which will then run code in the attribute and will also have knowledge about exactly how the method was called including parameter values.这样做的一种方法是使属性成为 AOP 元素,使用像 PostSharp 这样的框架或使用 Unity 框架等滚动你自己的框架。这将允许你通过用属性装饰它来将“拦截器”附加到方法,然后它将在属性中运行代码,并且还将了解该方法的确切调用方式,包括参数值。 Check out this blog: http://www.progware.org/Blog/post/Interception-and-Interceptors-in-C-(Aspect-oriented-programming).aspx查看此博客: http : //www.progware.org/Blog/post/Interception-and-Interceptors-in-C-(面向方面的编程) .aspx

I was able to get around this by using the following:我能够通过使用以下方法来解决这个问题:

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
        }
    }
}

And then on the specific methods you want to check Ids on,然后在您要检查 ID 的特定方法上,

[HttpGet]
[Route("{id}")]
[Authorize(requireIdClaim: true)]
public UserDetailsDto GetUserDetails(int userId)
{
    .. blah
}

And if you don't care to check their Id, but just that they're authenticated如果你不想检查他们的 ID,但只是他们已经过身份验证

[HttpGet]
[Route("")]
[Authorize]
public bool isLoggedIn()
{
    .. blah
}

Of course you can organize your authorize procedure however you like but this idea allows you to get their ID in your auth procedure there since it is passed in as route data.当然,您可以根据自己的喜好组织您的授权过程,但是这个想法允许您在那里的身份验证过程中获取他们的 ID,因为它是作为路由数据传入的。 More here: https://stackoverflow.com/a/16054886更多信息: https : //stackoverflow.com/a/16054886

Probably because this is an old post but this is now possible可能是因为这是一个旧帖子,但现在可以了

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM