【问题标题】:RuntimeBinderException with dynamic in C# 4.0C# 4.0 中动态的 RuntimeBinderException
【发布时间】:2011-02-08 09:03:05
【问题描述】:

我有一个界面:

public abstract class Authorizer<T> where T : RequiresAuthorization
{
    public AuthorizationStatus Authorize(T record)
    {
        // Perform authorization specific stuff
        // and then hand off to an abstract method to handle T-specific stuff
        // that should happen when authorization is successful

    }
}

然后,我有一堆不同的类,它们都实现了 RequiresAuthorization,相应地,每个类都有一个Authorizer&lt;T&gt;(一旦记录被授权,我域中的每个业务对象都需要不同的逻辑来执行)。

我也在使用 UnityContainer,我在其中注册了各种Authorizer&lt;T&gt;。然后我有一些代码如下,可以从数据库中找到正确的记录并对其进行授权:

void Authorize(RequiresAuthorization item)
{
    var dbItem = ChildContainer.Resolve<IAuthorizationRepository>()
                               .RetrieveRequiresAuthorizationById(item.Id);
    var authorizerType = type.GetType(String.Format("Foo.Authorizer`1[[{0}]], Foo",
                             dbItem.GetType().AssemblyQualifiedName));
    dynamic authorizer = ChildContainer.Resolve(type) as dynamic;

    authorizer.Authorize(dbItem);
}

基本上,我使用对象上的 Id 从数据库中检索它。在后台 NHibernate 负责弄清楚它是什么类型的 RequiresAuthorization。然后我想为它找到合适的授权者(我在编译时不知道我需要什么Authorizer&lt;T&gt; 实现,所以我有一点反思来获得完全限定的类型)。为此,我使用 UnityContainer 的 Resolve 方法的非泛型重载从配置中查找正确的授权方。

最后,我想在授权方上调用 Authorize,通过我从 NHibernate 取回的对象。

现在,针对问题:

在 VS2010 的 Beta2 中,上述代码完美运行。在 RC 和 RTM 上,只要我进行 Authorize() 调用,我就会得到一个 RuntimeBinderException 说“'Foo.Authorizer&lt;Bar&gt;.Authorize(Bar)' 的最佳重载方法匹配有一些无效参数”。当我在调试器中检查授权方时,它是正确的类型。当我在其上调用 GetType().GetMethods() 时,我可以看到采用 Bar 的 Authorize 方法。如果我在 dbItem 上执行 GetType(),它就是一个 Bar。

因为这在 Beta2 中有效,而在 RC 中无效,所以我认为这是一种回归(它似乎应该有效),所以我推迟了整理它,直到我有机会在 C# 的 RTM 版本上对其进行测试4.0。现在我已经这样做了,问题仍然存在。有人对这项工作有什么建议吗?

谢谢

特伦斯

【问题讨论】:

    标签: c# exception reflection dynamic


    【解决方案1】:

    Terence,我需要更多关于正在使用的类型及其定义的信息,以了解问题的真正原因,但这个错误基本上是告诉你它无法将 dbItem 转换为 Bar。有两种可能:

    1) RetrieveRequiresAuthorizationById() 返回dynamic,因此dbItem 的编译时类型被推断为dynamic。如果是这种情况,那么运行时绑定器将在运行时为dbItem 选择一个类型,如果可以找到,该类型本质上是最好的可访问类型。鉴于可访问性,此类型不可转换为 Bar。例如,dbItem 的运行时类型可能是一些不可访问的类型,其直接基类为object,显然object 不能转换为Bar

    2) RetrieveRequiresAuthorizationById() 返回一些静态类型。在这种情况下,静态类型在运行时不能转换为Bar

    我的猜测是(2)是这样的,dbItem 的类型是RequiresAuthorization。我也猜是一个接口。这不会转换为任何类类型。

    如果我是对的,那么您要做的就是使 dbItem 动态化。如果你这样做了,那么运行时绑定器将为dbItem 选择合适的类型,这大概就是你想要这样做的全部原因。

    void Authorize(RequiresAuthorization item)
    {
        var dbItem = ChildContainer.Resolve<IAuthorizationRepository>()
                                   .RetrieveRequiresAuthorizationById(item.Id);
        var authorizerType = type.GetType(String.Format("Foo.Authorizer`1[[{0}]], Foo",
                                 dbItem.GetType().AssemblyQualifiedName));
        dynamic authorizer = ChildContainer.Resolve(type) as dynamic;
    
        authorizer.Authorize(dbItem as dynamic); // <<<Note "as" here
    }
    

    【讨论】:

      猜你喜欢
      • 2014-09-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-05
      • 2014-10-15
      • 2011-07-04
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多