在C#4.0中使用动态的RuntimeBinderException

时间:2010-04-15 12:55:28

标签: c# exception reflection dynamic

我有一个界面:

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<T>(我的域中的每个业务对象在授权记录后都需要不同的逻辑来执行)。

我也在使用UnityContainer,我在其中注册了各种Authorizer<T>。然后我有一些代码如下,从数据库中找到正确的记录并授权它:

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(我不知道在编译时我需要Authorizer<T>的实现,所以我有一些反思来获得完全限定类型)。为此,我使用UnityContainer的Resolve方法的非泛型重载从配置中查找正确的授权器。

最后,我想在授权者上调用Authorize,传递我从NHibernate回来的对象。

现在,针对这个问题:

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

因为这在Beta2而不在RC中工作,我认为这是一个回归(看起来它应该工作)并且我推迟了整理它直到我有机会在RTM版本的C#上测试它4.0。现在我已经做到了,问题仍然存在。有没有人建议让这项工作?

谢谢

特伦斯

1 个答案:

答案 0 :(得分:11)

Terence,我需要更多关于游戏类型及其定义的信息,以了解问题究竟是什么,但此错误基本上告诉您它无法将dbItem转换为{{1} }。有两种可能性:

1)Bar返回RetrieveRequiresAuthorizationById(),因此编译时类型dynamic被推断为dbItem。如果是这种情况,则运行时绑定程序将在运行时选择dynamic的类型,如果可以找到,则基本上是最佳可访问类型。在给定可访问性的情况下,此类型无法转换为dbItem。例如,Bar的运行时类型可能是某些不可访问的类型,其直接基类为dbItem,显然object不能转换为object。< / p>

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

我的猜测是(2)是这种情况,Bar的类型是dbItem。其中我也猜测是一个界面。并且这不会转换为任何类型。

如果我是对的,你想要做的是让RequiresAuthorization动态。如果这样做,那么运行时绑定程序将为dbItem选择适当的类型,这可能是您想要执行此操作的全部原因。

dbItem