Handling custom attributes

杀马特。学长 韩版系。学妹 提交于 2019-12-11 17:35:27

问题


I have a custom attribute now I didn't know that how to restrict the access to the method on which I have applied my attribute.

For example: I have custom attribute say "CustomRole" now if value of CustomRole is "Admin" then and only then it should access method.

CustomRole["Admin"] 
public void Method()
{
    // code
}

How to perform verify the value?


回答1:


Your code looks a little bit wrong. Here is my class with the method with a CustomRoleAttribute

public class MyClass
{
      [CustomRole("Admin")]
      public void MyMethod()
      {


      }
}

You attribute should define the AttributeUsage to ensure other developers not uses your attribute on a property or constructor:

[AttributeUsage(AttributeTargets.Method, AllowMultiple = false,Inherited = true)]
public class CustomRoleAttribute : Attribute
{
        public string Role { get; private set; }

        public CustomRoleAttribute(string role)
        {
            Role = role;
        }
}

And now put both together:

MyClass myClass = new MyClass();
MethodInfo[] methods =  myClass.GetType().GetMethods(); // Access all the public methods.

        foreach (var methodInfo in methods) // iterate trough all methods.
        {

             // Get all custom attributes from the method.
             object[] attributes =  methodInfo.GetCustomAttributes(typeof (CustomRoleAttribute), true); 

            if (attributes.Length > 0)
            {
                CustomRoleAttribute attribute = (CustomRoleAttribute)attributes[0];
                if (attribute.Role == "Admin")
                {
                     // the role is admin
                }
             }
        }

You see now, how to use attributes. Bu you must first check the attribute and than access the method.




回答2:


You need some kind of aspect oriented programming approach here. Attribute itself can't 'access' the method as it is not evaluated by the runtime, but you might use some framework which will intercept the call, check the attribute and context and properly handle the case.

So in short, you will:

  • decorate a method with an attribute
  • provide an interceptor to handle the call
  • instantiate the class via some tools which provides AOP functionality
  • execute the call. The call will be intercepted and handled according to your implementation

Specifying the requirements

As you already noted, this can be easily specified with attributes:

[RequiredPermission(Permissions.CanCreateOrder)]
public virtual Guid CreateOrder(string orderCode) {...}

Intercepting the call

Now you need to pick a tool which will instantiate your object and intercept calls to it. This can be done with IoC containers which support AOP, or you can wrap it manually (e.g. use an AOP tool to create a proxy to the object and use the proxy).

You need to write an interceptor, or a wrapper method which has a chance to evaluate the call context before forwarding the execution to your method or rejecting the call.

You can find a discussion and code samples here. Take a look at OrderManagementService class which declares requirements via attribute.

Poor man's AOP

You can do all of this without resorting to proper AOP tools, but in a less generic way (which may be perfectly fine for simpler projects), using some form of Decorator pattern - please note, this is written from head, not in IDE:

interface IService 
{
    void Method(); 
}

class ServiceImpl : IService // one of many implementations
{
    [CustomRole("Admin")]
    public void Method() { ... } 
}

class ServiceChecker : IService // one of many implementations
{
    IService m_svc;
    public ServiceChecker(IService wrapped) { m_svc = wrapped; }

    public void Method() 
    {
        var mi = m_svc.GetType().GetMethod("Method");
        if(mi.IsDefined(typeof(CustomRoleAttribute), true)
        {
            CustomRoleAttribute attr =  (CustomRoleAttribute)mi.GetCustomAttributes(typeof(CustomRoleAttribute), true)[0];
            if(!attr.Role.Equals( GetCurrentUserRole() ) // depends on where you get user data from
            {
                throw new SecurityException("Access denied");
            }
        }
        m_svc.Method(); 
    } 
}

// the client code
IService svc = new ServiceChecker(new ServiceImpl());
svc.Method();


来源:https://stackoverflow.com/questions/12437368/handling-custom-attributes

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!