Как проверить, имеет ли метод атрибут (с интерфейсами, приведением и абстракцией)


Прочитав сообщение " Как проверить, есть ли у метода атрибут", я делаю один шаг, чтобы решить проблему, которая не дает мне спать.

Я представляю ситуацию:

( я работаю с ASP.Net MVC 4)

Эти интерфейсы :

public interface IFlyable
{
    ActionResult Fly();
}    

public interface IRunnable
{
    ActionResult Run();
}

Этот абстрактный класс :

public abstract class SuperHero : Controller
{
    public void SavePeople()
    {
    }    
}

Этот контроллер:

public class SuperManController : SuperHero,IFlyable,IRunnable {

    [Authorize]
    public ActionResult Fly(){
        // Flying...
    }    

    [Authorize]
    public ActionResult Run(){
        // Running...
    }    

}

Этот абстрактный класс (для тестов)

[TestClass]
public abstract class SuperHeroTest<TSuperHero>{

    protected abstract TSuperHero GetSuperHero();

    [TestMethod]
    public void IfSuperHeroCanFlyMustHaveAuthorizeAttribute(){

        var superHero=GetSuperHero();

        if(superHero is IFlyable)
        {
            var superHeroFlyable = (IFlyable) superHero;

            var have = MethodHasAuthorizeAttribute(() => superHeroFlyable.Fly());

            Assert.IsTrue(have);
        }

    }
}

И наконец этот класс наследуется от SuperHeroTest для проверки SuperManController:

[TestClass]
public class SuperManControllerTest : SuperHeroTest<SuperManController>{

    private SuperManController _superManController;

    public SuperManControllerTest(){
        _superManController=new SuperManController();
    } 


    protected override SuperManController GetSuperHero()
    {
        return _superManController;
    }

}

Метод MethodHasAuthorizeAttribute таков: (из сообщения выше)

public static MethodInfo MethodOf(Expression<System.Action> expression)
{
    MethodCallExpression body = (MethodCallExpression)expression.Body;
    return body.Method;
}

public static bool MethodHasAuthorizeAttribute( Expression<System.Action> expression )
{
    var method = MethodOf( expression );

    const bool includeInherited = false;
    return method.GetCustomAttributes(typeof(AuthorizeAttribute),includeInherited).Any();
}

Моя проблема такова:

Вызов MethodHasAuthorizeAttribute(() => superHeroFlyable.Fly()) в SuperHeroTest классе return false, когда он должен вернуть true.

(реализованный метод Fly в классе SuperManController имеет атрибут Authorize).

Я добавил атрибут Authorize в метод Fly в IFlyable и затем возвращает true.

public interface IFlyable
{
    [Authorize]
    ActionResult Fly();
}  

Как я могу сделать, чтобы MethodHasAuthorizeAttribute проверить реализацию а не интерфейс?

1 8

1 ответ:

С некоторыми модификациями метода IfSuperHeroCanFlyMustHaveAuthorizeattribute() вы можете заставить его работать.

Сначала проверьте, реализует ли контроллер интерфейс IFlyable. Если да, то получите MethodInfo для метода Fly контроллера. Тогда вам нужно только проверить атрибуты для возвращаемого MethodInfo. Таким образом, вы проверяете, имеет ли реализация атрибут вместо интерфейса.

Следующие работы ОК:

[TestClass]
public abstract class SuperHeroTest<TSuperHero>
{
    protected abstract TSuperHero GetSuperHero();

    [TestMethod]
    public void IfSuperHeroCanFlyMustHaveAuthorizeAttribute()
    {
        var superHero = GetSuperHero();

        if (superHero is IFlyable)
        {
            var superHeroFlyable = superHero;
            var method = typeof (TSuperHero).GetMethod("Fly");
            var hasAttribute = 
                method.GetCustomAttributes(typeof (AuthorizeAttribute), false).Any();
            Assert.IsTrue(hasAttribute);
        }
    }

    public static MethodInfo MethodOf(Expression<System.Action> expression)
    {
        var body = (MethodCallExpression)expression.Body;
        return body.Method;
    }

    public static bool MethodHasAuthorizeAttribute(Expression<System.Action> expression)
    {
        var method = MethodOf(expression);
        const bool includeInherited = false;
        return method.GetCustomAttributes(
            typeof(AuthorizeAttribute), includeInherited).Any();
    }
}