我有一个接口:

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负责找出它是什么类型的需求授权。然后我想为它找到合适的授权者(我不知道在编译时需要什么Authorizer<T>实现,所以我有一些反射来获得完全限定的类型)。为此,我使用unityContainer的resolve方法的非泛型重载从配置中查找正确的授权程序。
最后,我想对授权者调用authorize,通过从nhibernate返回的对象。
现在,针对这个问题:
在VS2010的beta2中,上述代码工作得很好。在rc和rtm上,只要我发出authorize()调用,就会得到一个runtimebinderexception,它说“与'Foo.Authorizer<Bar>.Authorize(Bar)'匹配的最佳重载方法有一些无效参数”。当我检查调试器中的授权程序时,它是正确的类型。当我对它调用getType().getMethods()时,可以看到authorize方法,它需要一个条。如果我对dbitem执行getType(),它就是一个条。
因为这在beta2中有效,而在rc中无效,所以我假设这是一个回归(看起来应该有效),并且我将它的排序推迟到有机会在c 4.0的rtm版本上进行测试之后。现在我做到了,问题仍然存在。有人有什么建议可以让这个工作吗?
谢谢
特伦斯

最佳答案

特伦斯,我需要更多关于游戏类型及其定义的信息来了解真正的问题是什么,但这个错误基本上告诉你它不能将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
}

08-27 11:14