是否可以通过反射引用特定版本的装配?

时间:2012-09-13 17:36:31

标签: c# reflection .net-assembly .net-4.5

我的一位同事不久前写了一段相当可疑的代码,最终它被打破了。这是简化的示例:

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)?

2 个答案:

答案 0 :(得分:3)

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

AssemblyName完整地描述了程序集的唯一标识。例如:

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

您可以在完整的程序集名称中指定版本控制信息。

Here是MSDN文档,包含更多示例。

答案 1 :(得分: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。