一千萬個為什麽

搜索

在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.Authorizer`1[[{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.

最後,我想在授權者上調用Authorize,傳遞我從NHibernate回來的對象。

現在,針對這個問題:

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.

因為這在Beta2而不在RC中工作,我認為這是一個回歸(看起來它應該工作)並且我推遲了整理它,直到我有機會在RTM版本的C#4.0上測試它。現在我已經做到了,問題仍然存在。有沒有人有任何建議讓這項工作?

謝謝

特倫斯

最佳答案

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()
                               .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);//<<

轉載註明原文: 在C#4.0中使用動態的RuntimeBinderException