C#4.0中具有动态的RuntimeBinderException [英] RuntimeBinderException with dynamic in C# 4.0

查看:181
本文介绍了C#4.0中具有动态的RuntimeBinderException的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个界面:

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,相应地,每个都有一个授权者< T> (我的域中的每个业务对象需要不同的逻辑才能执行一次记录被授权)。

Then, I have a bunch of different classes which all implement RequiresAuthorization, and correspondingly, an Authorizer<T> for each of them (each business object in my domain requires different logic to execute once the record has been authorized).

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

I'm also using a UnityContainer, in which I register various Authorizer<T>'s. I then have some code as follows to find the right record out of the database and authorize it:

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 。然后我想找到正确的授权者(我在编译时不知道什么实现授权者< T> 我需要,所以我有一点的反射获得完全合格的类型)。要实现这一点,我使用UnityContainer的Resolve方法的非泛型重载从配置中查找正确的授权者。

Basically, I'm using the Id on the object to retrieve it out of the database. In the background NHibernate takes care of figuring out what type of RequiresAuthorization it is. I then want to find the right Authorizer for it (I don't know at compile time what implementation of Authorizer<T> I need, so I've got a little bit of reflection to get the fully qualified type). To accomplish this, I use the non-generic overload of UnityContainer's Resolve method to look up the correct authorizer from configuration.

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

Finally, I want to call Authorize on the authorizer, passing through the object I've gotten back from NHibernate.

现在,出现问题:

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

In Beta2 of VS2010 the above code works perfectly. On RC and RTM, as soon as I make the Authorize() call, I get a RuntimeBinderException saying "The best overloaded method match for 'Foo.Authorizer<Bar>.Authorize(Bar)' has some invalid arguments". When I inspect the authorizer in the debugger, it's the correct type. When I call GetType().GetMethods() on it, I can see the Authorize method which takes a Bar. If I do GetType() on dbItem it is a Bar.

因为这在Beta2而不是RC中有效,我认为这是一个回归(似乎应该工作),我推迟了排序,直到我有机会在RTM版本的C#4.0上测试它。现在我已经做到了,问题依然存在。有人有任何建议可以使这项工作吗?

Because this worked in Beta2 and not in RC, I assumed it was a regression (it seems like it should work) and I delayed sorting it out until after I'd had a chance to test it on the RTM version of C# 4.0. Now I've done that and the problem still persists. Does anybody have any suggestions to make this work?

谢谢

Terence

推荐答案

Terence,我需要更多关于游戏类型及其定义的信息来知道问题真的是什么,但这个错误基本上告诉你它不能将 dbItem 转换为 Bar 。有两种可能性:

Terence, I'd need more information here about the types in play and their definitions to know what the problem really is, but this error is basically telling you that it could not convert dbItem to Bar. There are two possibilities:

1) RetrieveRequiresAuthorizationById()返回动态,因此编译时类型 dbItem 被推断为 dynamic 。如果是这种情况,那么运行时绑定程序将在运行时选择一个 dbItem 的类型,这本质上是可以找到的最佳访问类型。鉴于辅助功能,此类型不能转换为 Bar 。例如,它可能是 dbItem 的运行时类型是一些无法访问的类型,直接基类为对象显然对象不能转换为 Bar

1) RetrieveRequiresAuthorizationById() returns dynamic, and therefore the compile-time type of dbItem is inferred to be dynamic. If this is the case, then the runtime binder will select a type for dbItem at runtime that is essentially the best accessible type if can find. This type is not convertible to Bar given the accessibility. For example, it could be that dbItem's runtime type is some inaccessible type with a direct base class of object, and obviously object is not convertible to Bar.

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

2) RetrieveRequiresAuthorizationById() returns some static type. In that case, the static type is not convertible to Bar at runtime.

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

My guess is that (2) is the case, and that the type of dbItem is RequiresAuthorization. Which I am also guessing is an interface. And that's not going to be convertible to any class type.

如果我是对的,你想做的是使$ code> dbItem 动态。如果这样做,那么运行时绑定器将为 dbItem 选择适当的类型,这可能是您想要执行此操作的完整原因。

If I'm right, what you want to do is make dbItem dynamic. If you do, then the runtime binder will select the appropriate type for dbItem, which is presumably the whole reason you want to do this.

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
}

这篇关于C#4.0中具有动态的RuntimeBinderException的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆