【问题标题】:how to create a delegate on target class如何在目标类上创建委托
【发布时间】:2014-05-20 23:42:57
【问题描述】:

潜伏多年后第一次在这里发帖,在此先感谢您的帮助。

我试图在静态类中的控制器实例上创建委托,但出现错误: “无法绑定到目标方法,因为它的签名或安全透明度与委托类型的不兼容。”

错误发生在GetReasonsForDeny方法中,这里我传入了entity和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 问题;这些模式对许多人来说是新的,平台正在迅速成熟。

标签: c# asp.net-mvc


【解决方案1】:

您需要将控制器实例传递给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
{
   ...
}

【讨论】:

  • 感谢您的建议。我担心我必须传入控制器,因为我正在处理一个相当复杂的项目,我很确定我必须通过 3-6 个其他方法传递控制器,然后才能到达辅助方法负责评估行动。另外,我大大简化了控制器上的方法 CanPerformAction,实际上该方法以 Can 开头,后跟一个与控制器动作属性相同的方法名称,我们使用反射来查找所有可用的方法并限制访问.再次感谢。
  • 不幸的是,您在这里没有太多选择。主要问题是该方法引用了此类实例上的特定属性(在您的示例中为 UserRepository)。如果不传入实例,它就无法知道要使用的潜在的许多 UserRepositories 中的哪一个。如果 CanPerformAction 是静态的,这将不是问题
猜你喜欢
  • 2012-01-18
  • 2013-11-19
  • 2012-10-01
  • 2017-07-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多