简体   繁体   English

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

[英]Is it possible to reference specific version of assembly via reflection?

A colleague of mine wrote quite questionable piece of code some time ago, and eventually it got broken. 我的一位同事不久前写了一段相当可疑的代码,最终它被打破了。 Here's simplified sample: 这是简化的示例:

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

After some investigation it turned out that on my development machine there are indeed two parameters of MailMessage.Send method: 经过一番调查后发现,在我的开发机器上确实有两个MailMessage.Send方法的参数:

System.Net.Mime.BaseWriter writer
Boolean sendEnvelope

Hovewer, our QA engineers have installed VisualStudio 2012 recently, and got .NET 4.5 installed. Hovewer,我们的QA工程师最近安装了VisualStudio 2012,并安装了.NET 4.5。 So, when QA people try to run the application, they got System.Reflection.TargetParameterCountException . 因此,当QA人员尝试运行应用程序时,他们获得了System.Reflection.TargetParameterCountException And, it looks like MailMessage.Send got third parameter in .NET 4.5: 而且,看起来MailMessage.Send在.NET 4.5中获得了第三个参数:

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

Of course we are to re-implement this piece of code to stop using non-public interfaces. 当然,我们要重新实现这段代码以停止使用非公共接口。 Hovewer, we are on a tight schedule with a project, so we can't afford it right now. Hovewer,我们的项目时间紧迫,所以我们现在买不起。

So, here is a question: are there any ways to reference older (eg .NET 4.0) version of the assembly via reflection? 所以,这是一个问题:有没有办法通过反射引用程序集的旧版本(例如.NET 4.0)?

Instead of loading the Assembly with typeof(SmtpClient).Assembly you can load the assembly with Assembly.Load(AssemblyName) . 您可以使用Assembly.Load(AssemblyName)加载程序集,而不是使用typeof(SmtpClient).Assembly加载程序集。

AssemblyName describes an assembly's unique identity in full. AssemblyName描述了程序集的唯一标识。 For example: 例如:

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

You can specify versioning information in your full assembly name. 您可以在完整的程序集名称中指定版本控制信息。

Here is the MSDN documentation with more examples. 以下是MSDN文档以及更多示例。

To get specific, do this 要具体,请执行此操作

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");

Of course, this will only work with .Net 3.5 installed. 当然,这只适用于安装.Net 3.5。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM