如何在目标类上创建委托

时间:2014-05-20 23:42:57

标签: c# asp.net-mvc

经过多年的潜伏,第一次在这里发帖,提前感谢您的帮助。

我试图在静态类中创建一个控制器实例的委托,我得到错误: "无法绑定到目标方法,因为其签名或安全透明度与委托类型的方法不兼容。"

错误发生在方法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);

最后,我尝试创建一个非静态类,它将创建委托,然后将其返回到静态类,如下所示,但非静态类得到相同的错误:&#34;无法绑定到目标方法,因为其签名或安全透明度与委托类型的不兼容。&#34;

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

非常感谢任何建议!

1 个答案:

答案 0 :(得分: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
}

虽然稍微不相关的说明,如果您使用界面来强烈输入这些东西,那么您将使自己的生活变得更轻松,这样您根本不需要使用反射

e.g。

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

public class HomeController : Project.Web.Controllers.Base.Controller, ICanPerformAction
{
   ...
}