2009-10-01 24 views
2

我想使用Assembly.ReflectionOnlyLoad()從一些.NET系統程序集(如System,System.Windows.Forms等)中提取MemberInfos。現在我以這樣的方式展示它,我必須提供程序集的全限定名稱(包括版本信息和所有內容)或路徑。但是,我希望我的代碼不依賴於特定的版本。相反,我只想提供部分名稱(「System.Windows.Forms」),然後加載該程序集的最新版本。如果存在的話,另一種方法是GAC中程序集的路徑。C#反射加載沒有FQN的「系統」程序集

我想必須有一種方法,因爲Visual Studio似乎也這樣做。當您查看參考部分中的項目文件時,只能指定「System.Windows.Forms」並且沒有更進一步的版本信息,但VS會在項目中引用正確的程序集版本。有人知道我可以做到這一點嗎?

非常感謝!

+0

如果你看一下在Visual Studio中的參考屬性,你會看到組件的版本號 – 2009-10-01 22:17:57

+0

系統應該已經在非反射唯一的國家被加載。 – 2009-10-01 22:32:43

回答

0

ReflectionOnlyLoad()最終調用專用nLoad()方法trueforIntrospection參數。另一方面,LoadWithPartialName()(其具有您希望的程序集查找行爲)還使用不同的參數集(和forIntrospection)委託給nLoad()。用反思複製部分調用是一個簡單的反思問題。 :)

更新:其實並不那麼簡單。如果nLoad()失敗,我們需要致電私人EnumerateCache(),然後不同的InternalLoad()。我的機器上的以下作品:

[Test] 
public void TestReflectionOnlyLoadWithPartialName() 
{ 
    var l = ReflectionOnlyLoadWithPartialName("System.Windows.Forms"); 

    Assert.IsTrue(l.ReflectionOnly); 
} 

public Assembly ReflectionOnlyLoadWithPartialName(string partialName) 
{ 
    return ReflectionOnlyLoadWithPartialName(partialName, null); 
} 

public Assembly ReflectionOnlyLoadWithPartialName(string partialName, Evidence securityEvidence) 
{ 
    if (securityEvidence != null) 
     new SecurityPermission(SecurityPermissionFlag.ControlEvidence).Demand(); 

    AssemblyName fileName = new AssemblyName(partialName); 

    var assembly = nLoad(fileName, null, securityEvidence, null, null, false, true); 

    if (assembly != null) 
     return assembly; 

    var assemblyRef = EnumerateCache(fileName); 

    if (assemblyRef != null) 
     return InternalLoad(assemblyRef, securityEvidence, null, true); 

    return assembly; 
} 

private Assembly nLoad(params object[] args) 
{ 
    return (Assembly)typeof(Assembly) 
     .GetMethod("nLoad", BindingFlags.NonPublic | BindingFlags.Static) 
     .Invoke(null, args); 
} 

private AssemblyName EnumerateCache(params object[] args) 
{ 
    return (AssemblyName)typeof(Assembly) 
     .GetMethod("EnumerateCache", BindingFlags.NonPublic | BindingFlags.Static) 
     .Invoke(null, args); 
} 

private Assembly InternalLoad(params object[] args) 
{ 
    // Easiest to query because the StackCrawlMark type is internal 
    return (Assembly) 
     typeof(Assembly).GetMethods(BindingFlags.NonPublic | BindingFlags.Static) 
     .First(m => m.Name == "InternalLoad" && m.GetParameters()[0].ParameterType == typeof(AssemblyName)) 
     .Invoke(null, args); 
} 
相關問題