как создать делегата на целевой класс

1

В первый раз, отправляя сюда после нескольких лет скрытия, заблаговременно за любую помощь.

Я пытаюсь создать делегат на экземпляре контроллера из статического класса, и я получаю сообщение об ошибке: "Невозможно связать с целевым методом, потому что его подпись или прозрачность безопасности несовместимы с сигнатурой типа делегата".

Ошибка возникает в методе GetReasonsForDeny, где я передаю объект и typeof (HomeController).

Мой код здесь:

public class HomeController : Project.Web.Controllers.Base.Controller
{
    //Properties
    IUserRepository UserRepository { get; set; }

    //Constructor
    HomeController(IUserRepository userRepository)
        : Project.Web.Controllers.Base.Controller
    {
        UserRepository = userRepository;
    }

    public List<string> CanPerformAction(IEntity entity)
    {
        List<string> reasonsForDeny = new List<string>();
        TestEntity domainEntity = entity as TestEntity;

        if (domainEntity != null)
            VerifyRules(domainEntity, UserRepository, out reasonsForDeny);

        return reasonsForDeny;
    }
}

public static class ControllerActionHelper
{
    private static List<string> GetReasonsForDeny(IEntity entity, Type Controller)
    {
        List<string> reasonsForDeny = new List<string>();

        MethodInfo accessMethod = controller.GetMethod("CanPerformAction");
        if (accessMethod != null)
        {
            /***** Error Here ********/
            Func<IEntity, List<string>> accessDelegate = (Func<IEntity, List<string>>)Delegate.CreateDelegate(typeof(Func<IEntity, List<string>>), controller, accessMethod);

            reasonsForDeny = accessDelegate(entity);
        }

        return reasonsForDeny
    }
}

Я также попытался изменить делегирование на статический, передав null в CreateDelegate, как показано ниже, но если я это сделаю, то когда CanPerformAction вызывается, мой UserRepository имеет значение null.

// Before
Func<IEntity, List<string>> accessDelegate = (Func<IEntity, List<string>>)Delegate.CreateDelegate(typeof(Func<IEntity, List<string>>), controller, accessMethod);

// After
Func<IEntity, List<string>> accessDelegate = (Func<IEntity, List<string>>)Delegate.CreateDelegate(typeof(Func<IEntity, List<string>>), null, accessMethod);

Наконец, я попытался создать нестатический класс, который создаст делегат, а затем вернет его в статический класс, как показано ниже, но нестатический класс получает ту же ошибку: "Невозможно связать с целевым методом, потому что его подпись или прозрачность безопасности несовместима с прозрачностью типа делегата ".

public static class ControllerActionHelper
{
    private static List<string> GetReasonsForDeny(IEntity entity, Type Controller)
    {
        List<string> reasonsForDeny = new List<string>();

        MethodInfo accessMethod = controller.GetMethod("CanPerformAction");
        if (accessMethod != null)
        {
            var tempInstance = new foo();

            Func<IEntity, List<string>> accessDelegate = foo.MakeMyDelegatePlease(controller, accessMethod, entity);

            reasonsForDeny = accessDelegate(entity);
        }

        return reasonsForDeny
    }
}

public class foo
{
    public Func<IEntity, List<string>> MakeMyDelegatePlease(Type controller, MethodInfo accessMethod, IEntity entity)
    {
        /********* Error Here ************/
        Func<IEntity, List<string>> accessDelegate = (Func<IEntity, List<string>>)Delegate.CreateDelegate(typeof(Func<IEntity, List<string>>), controller, accessMethod);

        return accessDelegate;
    }
}

Любой совет будет очень благодарен!

Теги:
asp.net-mvc

1 ответ

2

Вам нужно передать экземпляр контроллера в GetReasonsForDeny, а не только его тип, поскольку CanPerformAction - это метод на конкретном экземпляре HomeController.

private static List<string> GetReasonsForDeny(IEntity entity, object controller)
{
    List<string> reasonsForDeny = new List<string>();

    MethodInfo accessMethod = controller.GetType().GetMethod("CanPerformAction");
    if (accessMethod != null)
    {
        /***** Error Here ********/
        Func<IEntity, List<string>> accessDelegate = (Func<IEntity, List<string>>)Delegate.CreateDelegate(typeof(Func<IEntity, List<string>>), controller, accessMethod);

        reasonsForDeny = accessDelegate(entity);
    }

    return reasonsForDeny
}

Однако на немного несвязанной ноте вы сделаете жизнь намного легче для себя, если бы вы использовали интерфейс, чтобы сильно набирать этот материал, чтобы вам вообще не нужно было использовать отражение

например

interface ICanPerformAction
{
    List<string> CanPerformAction(IEntity entity);
}

public class HomeController : Project.Web.Controllers.Base.Controller, ICanPerformAction
{
   ...
}
  • 0
    Я ценю совет. Я волновался, что мне придется передать контроллер, поскольку я имею дело с довольно сложным проектом, и я почти уверен, что мне придется передать контроллер через 3-6 других методов, прежде чем он перейдет к вспомогательному методу, который несет ответственность за оценку действия. Кроме того, я значительно упростил метод CanPerformAction на контроллере, в действительности метод начинается со слова Can, за которым следует имя метода, идентичное атрибуту действия контроллера, для которого мы используем отражение, чтобы найти все доступные методы и ограничить доступ к нему. , Еще раз спасибо.
  • 0
    К сожалению, у вас нет большого выбора здесь .. Основная проблема заключается в том, что метод ссылается на определенное свойство в экземпляре этого класса (в вашем примере это UserRepository). Не передавая экземпляр, он не может знать, какой из потенциально многих UserRepositories использовать. Если бы CanPerformAction был статическим, это не было бы проблемой

Ещё вопросы

Сообщество Overcoder
Наверх
Меню