8

我需要獲取有關調用我的組件的程序集的元數據。因此,使用Assembly.GetCallingAssembly()似乎是天作之合。不過,我發現它在除Windows Store以外的任何地方都可以使用。在那裏的支持:WinRT不支持Assembly.GetCallingAssembly,但用於可移植類庫?

但是,如果它不支持直接在Windows Store應用程序中。我可以創建一個可移植的類庫,然後在Windows應用商店應用內部調用它,但我不能直接將它放在Windows應用商店應用/類庫中。

是否有解決方法或通過其他方式獲取由Assembly提供的元數據類型?

回答

7

Assembly.GetCallingAssembly沒有暴露在WinRT中 - 據說是因爲其語義的內聯等(source)的臉是不可靠的,但它也並不適合過多在Windows Store應用程序允許受限制的反映。你可以得到類似Assembly.GetCurrentAssembly(),例如像這樣:

typeof(MainPage).GetTypeInfo().Assembly 

但是,這是不一樣的。使用受限反射模型,在.NET中儘可能在運行時獲取堆棧跟蹤也是不可能的。

至於便攜式類庫,我想說Assembly.GetCurrentAssembly()通常在可移植類庫中得到支持,但只是在WinRT中不支持 - 如果它不在該平臺中,這將有意義。但實際上,它似乎在除WinRT + .NET4.5以外的所有配置文件(包括WinRT)中都存在 - 看起來在這種不一致的情況下必定會有某種疏忽。因此,WinRT中存在的方法(此外,還沒有類型的重定向正在進行),但在編譯時可用的元數據中不可見。

因此,您可以調用該方法與反思:

var assembly = (Assembly) typeof(Assembly).GetTypeInfo() 
    .GetDeclaredMethod("GetCallingAssembly") 
    .Invoke(null, new object[0]); 

我相信在Windows應用商店中的應用程序這種方法的不可見性是「我們希望這將消失」。

(這個答案只關心「我可以」而不是「我應該」)。

2

該方法被切斷,因爲它在WinRT應用程序中太不可靠。 WinRT的強大設計目標是使不同語言運行時環境之間的互操作變得簡單和無故障。這很好,你可以用像C#這樣的語言輕鬆創建一個WinRT組件,並讓它被一個用C++或Javascript之類的非託管語言編寫的應用程序使用。

這在桌面.NET應用程序中也是可行的,但它要複雜得多,必須回退到[ComVisible]程序集或使用C++/CLI語言創建混合模式程序集。在這種情況下使用Assembly.GetCallingAssembly()也會失敗,但是由於他非常清楚要做一些特殊的事情,所以程序員完全可能會失敗。

這在WinRT組件中變得更加模糊。特別是因爲如果調用實際上是從另一個.NET程序集創建的,它不一定會失敗。但是當它來自非託管代碼時沒有希望。

這種隨機類型的失敗只是徹底的痛苦,沒有一個體面的解決方法。因此該方法被切斷。使用PCL是一種可能的解決方法,但微軟過去一直嚴厲警告說,這種黑客行爲是非常不推薦的。非零賠率將被商店驗證程序捕獲並導致拒絕。