AssemblyInstaller Bug(Constructor(Assembly, String[]) source code issue)

本文描述了一个关于.NET框架中AssemblyInstaller类的初始化问题,详细解释了如何通过调用HelpText属性触发AssemblyInstaller对Assembly的反射检查,从而实现对Installers集合的正确初始化。

哎,今天又碰到一个问题,算是一个.Net小bug吧

Installers集合未正常初始化在调用AssemblyInstaller构造函数时

 

LibraryContainInstallerClass.dll是一个拥有installer class的dll。

            Assembly assembly = Assembly.LoadFrom("LibraryContainInstallerClass.dll");

            AssemblyInstaller installer = new AssemblyInstaller(assembly, new string[] { });
            if (installer.Installers.Count > 0)
            {
          statement1
            }

在installer.Installers.Count移行添加一个断点

运行此代码,然后程序会如期的停在Count那一行,然后将鼠标直接放到Count属性上读取其值,你会发现此时是0,并且按下F11,让程序继续运行,你会发现程序运行路径跳过了if内部结构statement1,即结果是按0运行的。

再次运行代码,这次还是直接将鼠标移动到Count属性上读值,结果还是0,同上次一样;但这次我们再把鼠标移至installer上面,并且打开它的折叠加号(+),使其属性对你可见,然后再把鼠标移至Count属性上读值,你会发现此时的结果是1,然后你按下F11,你会发现程序继续运行的路径是按照1来选择的,没有执行statement1

客户很是奇怪,其实我TMD也奇怪,他以为这是debugger的bug,我刚开始也以为是debugger的bug,真TMD邪门儿了。

后来调试.Net源码,在InstallerCollection的Add方法处加了个断点,然后再在你的代码中添加installer.Install方法调用,当程序停在断点处时,看到CallStack中的方法调用发现,他在Add之前对assembly(LibraryContainInstallerClass.dll)进行了reflection检查(AssemblyInstaller.InitializeFromAssembly),并通过,将其添加进Installers集合。

Got it!

原来AssemblyInstaller的构造函数本身就没有对传入参数Assembly做任何操作,其实我感觉,本来的设计应该是调用AssemblyInstaller.InitializeFromAssembly方法,来检查传入的Assembly是否含有installer class,然后对Installers集合做操作,进行初始化。如果你会使用Reflector查看这个源码时,你会发现AssemblyInstaller.InitializeFromAssembly方法只在一下方法中使用:

image

也许.Net是在别处使用了InitializeFromAssembly中类似的代码做了操作,但是从我现在的分析来看,应该在AssemblyInstaller构造函数中就调用此方法来检查Assembly并选择将其中的installer加入Installers属性集合中进行初始化。

所以对此问题,现在的解决方案是调用一次get_HelpText()方法,即AssemblyInstaller.HelpText 属性,促使程序对传入的assembly进行reflection,检查,并加入到Installers集合中。

Debugger在此案例中,只是一个配角,其实原因是因为你在查看 installer并选择展开他的折叠加号,让所有属性对你可见时,程序调用了HelpText属性,InitializeFromAssembly方法也就被执行了,Installers集合也就被添加值了。

不说了我该给客户回帖了,拜拜!

问题来源:http://social.msdn.microsoft.com/Forums/en-US/vsdebug/thread/89d77f92-7792-4a1f-80b5-c4c07b8f1764/

转载于:https://www.cnblogs.com/telnet_mike/archive/2011/09/23/2186510.html

### 构造函数未定义问题的原因分析 在 Java 中,当编译器报告 `constructor Phone(String, double, String) is undefined` 错误时,这通常意味着程序尝试通过指定参数调用类的构造函数,而该类并未提供匹配这些参数类型的构造函数[^1]。 如果存在一个名为 `Phone` 的类,则此错误可能由以下原因引起: - 类 `Phone` 缺少具有 `(String, double, String)` 参数签名的构造函数。 - 如果默认无参构造函数被显式定义,则编译器不会自动生成其他形式的构造函数[^2]。 因此,在这种情况下,需要手动为 `Phone` 定义合适的构造方法来接受三个特定类型的参数 (即 `String`, `double`, 和另一个 `String`)。 以下是解决问题的一个典型实现方式: ```java public class Phone { private String model; private double price; private String color; // 正确地定义了一个接收 (String, double, String) 参数的构造函数 public Phone(String model, double price, String color){ this.model = model; this.price = price; this.color = color; } @Override public String toString(){ return "Model: "+model+", Price: $"+price+", Color: "+color; } } // 使用示例 class Test{ public static void main(String[] args){ // 创建对象实例并初始化其属性值 Phone myPhone = new Phone("iPhone X", 999.0, "Space Gray"); System.out.println(myPhone); } } ``` 上述代码展示了如何正确定义以及使用带有具体参数列表的构造函数。注意这里的关键在于确保所创建的对象能够传递正确的数据类型给对应的字段成员变量[^3]。 #### 解决方案总结 为了消除此类编译期错误消息,应该检查目标类是否有适当参数配置下的公共访问权限修饰符(public)构造子;如果没有的话就需自行补充进去以满足实际需求场景中的实例化操作要求。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值