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

然而,我们的 QA 工程师最近安装了 VisualStudio 2012,并安装了 .NET 4.5。因此,当 QA 人员尝试运行应用程序时,他们得到了System.Reflection.TargetParameterCountException. 而且,看起来MailMessage.Send在 .NET 4.5 中有第三个参数:

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

当然我们要重新实现这段代码来停止使用非公共接口。但是,我们的项目时间很紧,所以我们现在负担不起。

所以,这里有一个问题:有没有办法通过反射来引用旧版本(例如 .NET 4.0)的程序集?

4

2 回答 2

3

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

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

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

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

是带有更多示例的 MSDN 文档。

于 2012-09-14T07:46:34.963 回答
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。

于 2012-09-14T08:04:52.543 回答