写一个CS文件,代码如下:
using System;
namespace Me

    public class Student
    {
        public Student()
        { 
        
        }
        public void Print()
        {
            Console.WriteLine("我是人");
        }
    }
}
用csc.exe转换为dll文件,在另一个项目中加载,代码如下:
 static void Main(string[] args)
        {
            Console.WriteLine(Assembly.LoadFile("D:\\1.dll").CreateInstance("Me.Student").GetType().ToString());  //打印出类别为:Me.Student,无错。
              ((Me.Student)Assembly.LoadFile("D:\\1.dll").CreateInstance("Me.Student")).Print();//报错:无法将类型为“Me.Student”的对象强制转换为类型“Me.Student”。        
            
        }
以上错误,本人苦思几天不明其理,希望大家各自发表自己的看法,一起探讨这个问题。本人菜鸟,麻烦大家说仔细点。

解决方案 »

  1.   

    第一行得到的是Type的ToString方法,该方法获得Type的Name当然是Student。此时的类型是Type不是Student。既然不是Student类型转换当然失败。你可以通过Type.GetProperty("Student")来获得Property,然后在获得该PropertyInfo的value即可。
      

  2.   


    匪夷所思,怎么会想出 Type.GetProperty("Student")来呢?
      

  3.   

    1楼的不对吧?CreateInstance("Me.Student")返回的应该是Me.Student
    2楼的,你知道为什么吗?今天问老师,他也没说清楚。
      

  4.   

    很难说的问题出自哪里,只能估计。你的“另一个项目”可能已经引用了Me所在的dll,然后又用LoadFile装载了另一个——注意,是另一个dll文件。这是一个知识点:.net实际上可以装载同一命名空间、同一类型的多个类型实例。也就是说,一个student来自于一个dll,而另一个student来自于另一个dll文件,他们在不同的文件中。在.net中,可以有多个 Me.Student 类,只要他们在不同的dll中,就可以。
    你可以把1.dll复制成为2.dll,然后就可以使用LoadFile分别装入它们,并且分别实例化。
      

  5.   

    所以,实际上严格来说,假设两个类型的命名空间、名称都完全一样,并不能说他们是同一类型。只不过,我们的c#、vb.net等编译器通常都不允许源代码这样引用两个命名有冲突的dll。但是.net平台底层实际上是完全允许这样的。
      

  6.   

    底层系统这样实现有一个显而易见的好处,例如我们在asp.net网站上上传新的dll,那么使用原来的dll的程序(严格来说是使用原来的dll文件复制到windows临时目录里边的dll副本的程序)可以继续执行,而新的程序则会直接使用新的dll,内存中有两份类型明重复的assembly。等使用原来dll的程序结束,系统就可以(因为长时间不使用而)卸载原来的dll了。这样就可以在程序运行时不中断程序就动态更新dll。
      

  7.   

    很感谢你的回答,不过答案我觉得不对,因为我确定没有在其他项目中引用同一个dll,继续等待。
      

  8.   

    给一段我做的装载插件代码断,希望对你有帮助:
            public bool LoadPlugIn(string arg_strFileName, string arg_strInterface) {
                Assembly pluginAssembly;
                Type pluginType;
                IQCPrjPlugin PluginInterface;
                try {
                    pluginAssembly = Assembly.LoadFrom(arg_strFileName);
                    pluginType = pluginAssembly.GetType(arg_strInterface);
                    if (null == pluginType) {
                        MessageBox.Show("插件接口获取失败!\n" + "  插件:" + arg_strFileName + "\n" + "  接口:" + arg_strInterface,"错误:",MessageBoxButtons.OK,MessageBoxIcon.Error);
                        return false;
                    }
                    PluginInterface = (IQCPrjPlugin)Activator.CreateInstance(pluginType);
                    PluginInterface.init_plugin();
                    m_IPlugins.Add(PluginInterface);
                }catch (Exception e) {
                    MessageBox.Show(e.Message);
                    MessageBox.Show(System.Environment.StackTrace);
                    return false;
                }
                return true;
            }
      

  9.   

    Activator.CreateInstance("Namespace,Assembly");
      

  10.   


    如果你没有引用另一个dll(注意是另一个,而不是同一个),你的代码((Me.Student)Assembly.LoadFile("D:\\1.dll").CreateInstance("Me.Student")).
    中的强制类型转换代码就不可能编译通过!能够强制类型转换,就说明你首先引用了一个dll,这个dll中的模块包含Me.Student定义。而你装入的d:\1.dll有99%的可能性并不是应用程序运行时(通常自动复制到)在bin\debug或者bing\release目录下的dll。这样就有两个不同来源的dll被装载进入应用程序域了。
      

  11.   

    嗯修正一下上面的说法,其实是不是引用d:\1.dll也不是关键的因素。因为引用它,运行时并不是就装入它,而是装入复制之后的dll。
      

  12.   


    正解... 必须保证 D:\\1.dll类Me.Student和你的Me.Student 是同一个程序集..... 
    也就是说  你的程序集必须引用这个dll才可以...
    另外
    方法1 如果不引用..那就做接口dll 两边都引用.到时候转换为接口
    方法2 一路反射调用到底.. 
      

  13.   

    我是在同一个项目中引用了d:\1.dll,又用Assembly.LoadFile()方法加载同一个dll,这样有错吗?
    谢谢大家   
      

  14.   

    谢谢你,我明白了,虽然两个dll内容一样,但是路径不同所以报错。编译器不允许这样做,但是.net平台底层实际上是完全允许这样的。这句话真棒。这个反射真不好学呢,感觉你人很好,可以交个朋友吗?我留下自己的QQ,如果可以,你加我吧。好几次在CSDN看到你的留言,感觉你很热心,不浮躁。