反思和铸造

时间:2009-04-22 15:39:16

标签: .net reflection

我有以下场景,当我尝试强制转换时抛出异常:

  1. 我添加了一个项目引用并导入了项目的命名空间。
  2. LoadFile行加载构建此项目时生成的dll。
  3. 我正在尝试访问从dll修饰对象属性的属性的公共字段。
  4. 以下是例外文字:
  5.   

    [A] MyNamespace.PropertyMetaDataAttribute无法强制转换为[B] MyNamespace.PropertyMetaDataAttribute。类型A源自位于'C:\ projectA \ bin \ debug \ A.dll'的上下文'LoadFrom'中的'A,Version = 12.0.0.25,Culture = neutral,PublicKeyToken = null'。类型B源自位于'C:\ currentProject \ bin \ debug \ A.dll'的上下文'Default'中的'A,Version = 12.0.0.25,Culture = neutral,PublicKeyToken = null'。

    代码段:

    using MyNamespace; // added project reference to this item
    
    m_Assembly = Assembly.LoadFile(ConfigurationManager.AppSettings["DLL_File_Path"]);
    
     Type objectType = m_Assembly.GetType(string.Format("{0}.{1}", NAMESPACE_PREFIX, "MyObject"));
    
     // Crash happens on line below:
    
     Attribute attr = (Attribute) objectType.GetProperty("Name").GetCustomAttributes(false)[0];
    
    //This is the layout of the object which has the property
     MyObject
     {
        [MyAttribute(Name="FooName")]
        Foo {get;set;}
     }
    
    // This is the definition of the attribute
     MyAttribute :Attribute
     {
        // Want to access the value
        public string Name = string.Empty;
     }
    

3 个答案:

答案 0 :(得分:4)

好像是你的

ConfigurationManager.AppSettings["DLL_File_Path"]

指向其他位置的相同dll,因此.Net运行时尝试加载已加载的dll,当您尝试使用它时,Type System会因为2 dll之间重复的类型而爆炸。

根据错误,这些是两个dll的位置

  • C:\ currentProject \ BIN \调试\ A.DLL
  • C:\了projectA \ BIN \调试\ A.DLL

如果在解决方案上显式设置了引用,则可以尝试将copy local设置为False,以便在解决方案生成时,不要复制依赖项的结果

答案 1 :(得分:1)

如果你的dll已经在自动搜索的路径中(当前目录,bin等),并且由于你引用了该程序集中的内容而加载了你的LoadFile(你可能想要使用LoadFrom)也会将相同的DLL加载到另一个上下文(LoadFrom-context)而不是默认值。

您应该考虑仅加载DLL一次,或者首先尝试从默认上下文中获取程序集,以避免冲突,方法是查看AppDomain.CurrentDomain.GetAssemblies()。

如果您尝试访问不在默认上下文中的程序集,您甚至可以将AssemblyResolve-eventhandler作为后备附加到AppDomain.CurrentDomain。

http://msdn.microsoft.com/en-us/library/system.appdomain.assemblyresolve.aspx

AppDomain.CurrentDomain.GetAssemblies()将包含来自所有上下文的程序集,甚至包含使用LoadFrom / LoadFile加载的程序集。

答案 2 :(得分:1)

加载程序集时,可以将类型加载到不同的上下文中。这就是为什么你不能从一种类型转换为另一种类型的原因。您可以使用AssemblyResolve事件解决这个问题(正如jishi建议的那样),或者还有一个TypeResolve事件可以在您使用时返回正确的类型,但我认为您确实需要对齐装配到正确的上下文,并了解它的加载时间和方式以及适合您的方法。

Suzanne Cook博客的这些文章确实帮助我理解了不同的背景以及如何将事物加载到它们中以及为什么。

http://blogs.msdn.com/suzcook/archive/2003/09/19/loadfile-vs-loadfrom.aspx

http://blogs.msdn.com/suzcook/archive/2003/05/29/57143.aspx

另外,如果你想看看它们是如何以及为什么被加载的,你应该看看Fusion logs并将它们设置为转储所有信息,它将显示程序集的加载信息。