在C＃4.0中使用動態的RuntimeBinderException

public abstract class Authorizer 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

}
}


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

I'm also using a UnityContainer, in which I register various Authorizer'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()
.RetrieveRequiresAuthorizationById(item.Id);
var authorizerType = type.GetType(String.Format("Foo.Authorizer1[[{0}]], Foo",
dbItem.GetType().AssemblyQualifiedName));
dynamic authorizer = ChildContainer.Resolve(type) as dynamic;

authorizer.Authorize(dbItem);
}


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 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.

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.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.

最佳答案

Terence，我需要更多關於遊戲類型及其定義的更多信息，以了解問題究竟是什麽，但這個錯誤基本上告訴你它無法將 dbItem 轉換為 Bar </代碼>。有兩種可能性：

1） RetrieveRequiresAuthorizationById（）返回 dynamic ，因此 dbItem 的編譯時類型被推斷為 dynamic 。如果是這種情況，那麽運行時綁定程序將在運行時為 dbItem 選擇一個類型，如果可以找到，它本質上是最好的可訪問類型。在給定可訪問性的情況下，此類型無法轉換為 Bar 。例如，可能是 dbItem 的運行時類型是一些具有直接基類 object 的不可訪問類型，顯然 object 不是可轉換為 Bar 。

2） RetrieveRequiresAuthorizationById（）返回一些靜態類型。在這種情況下，靜態類型在運行時不能轉換為 Bar

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

authorizer.Authorize(dbItem as dynamic);//<<