2012-09-13 68 views
1

前段時間,我的一位同事寫了一段頗有疑問的代碼,最終被破壞了。這裏的簡單示例:是否可以通過反射來引用特定版本的程序集?

Assembly assembly = typeof(SmtpClient).Assembly; 
Type _mailWriterType = assembly.GetType("System.Net.Mail.MailWriter"); //getting a reference to internal class 

//create an instance of System.Net.Mail.MailWriter storing it into _mailWriter variable 
//It's internal, but for now it still works 

MethodInfo _sendMethod = typeof(MailMessage).GetMethod("Send",BindingFlags.Instance | BindingFlags.NonPublic); 

//calling non-public method resulting in app crash 
_sendMethod.Invoke(
    message, 
    BindingFlags.Instance | BindingFlags.NonPublic, 
    null, 
    new object[] { _mailWriter, true }, 
    null); 

經過一番調查事實證明,我的開發機器上的確是有MailMessage.Send方法的兩個參數:

System.Net.Mime.BaseWriter writer 
Boolean sendEnvelope 

Hovewer,我們的QA工程師已經安裝的VisualStudio 2012最近,和安裝了.NET 4.5。所以,當QA人嘗試運行應用程序時,他們得到了System.Reflection.TargetParameterCountException。而且,它看起來像MailMessage.Send在.NET 4.5得到了第三個參數:

System.Net.Mime.BaseWriter writer 
Boolean sendEnvelope 
Boolean allowUnicode 

當然,我們要重新實現這段代碼停止使用非公共接口。 Hovewer,我們的項目時間緊迫,所以我們現在買不起。

因此,這裏有一個問題:有沒有什麼方法可以通過反射來引用程序集的舊版本(例如.NET 4.0)?

+0

爲什麼不只是在項目上強制目標框架.NET 4.0? –

+0

它被迫爲3.5。不幸的是,似乎通過反思的後期綁定並沒有考慮到它。 – J0HN

+0

很好的現實世界爲什麼這種類型的代碼發臭+1。 – Jodrell

回答

3

而不是用typeof(SmtpClient).Assembly加載程序集,您可以使用Assembly.Load(AssemblyName)加載程序集。

AssemblyName完整描述了一個程序集的唯一標識。例如:

ExampleAssembly, Version=1.0.0.0, Culture=en, PublicKeyToken=a5d015c7d5a0b012 

您可以指定您的全名裝配版本信息。

Here是帶有更多示例的MSDN文檔。

+0

這是完全正確的,但不幸的是它並沒有解決潛在的問題。從QA框中的4.0版本提取的方法仍然有三個參數。謝謝你的回答,無論如何:) – J0HN

+0

我不能使這Assembly.Load工作。如果我手動將版本號(調試時)更改爲2.0.0.0,然後加載版本1.0.0.0。 – Pompair

0

得到具體,做到這一點

var systemNet35 = Assembly.Load(
    @"System.Net, Version=3.5.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"); 

Type _mailWriterType = systemNet35.GetType("System.Net.Mail.MailWriter"); 

當然,這隻有在安裝了.NET 3.5的工作。

相關問題