2011-11-19 55 views
0

在我的情况下有三个组件:Consumer类,IExposedIface接口和Exposed类实现IExposedIfaceConsumerExposed都与IExposedIface静态链接,但Consumer没有编译时参考Exposed动态加载程序集:为什么此代码有效?

我想拿出一个方案,该方案将允许Consumer在运行时加载不同版本的Exposed(取决于输入数据 - 假设每个输入文件携带其中Exposed版本应该被用来处理它的信息) 。为了实现这一点,我开始研究AppDomains,现在我有一个基本版本的工作。

到目前为止,在提供IExposedIface组件到Exposed组件时,有两种选择。

  1. 只在ConsumerIExposedIface.dll目录和处理AppDomain.AssemblyResolve事件为AppDomain中,我创建的Exposed

  2. ConsumerIExposedIface.dll两个实例的目录以及每个Exposed.dll

现在考虑的是我建立Exposed反对这种IExposedIface

public interface IExposedIface 
{ 
    string SaySomething();  
} 

和我建立Consumer反对这种IExposedIface

public interface IExposedIface 
{ 
    string SaySomething(); 
    string SaySomethingDifferent(); 
} 

在第一种情况下,异常

例外:方法'SaySomethingDifferent'类型'Exposed.Exposed'从 程序集'Exposed,Version = 1.0.0.0,Culture = neutral,PublicKeyToken = null'没有执行

在那一刻我打电话appDomain.CreateInstanceAndUnwrap(...)在新创建的AppDomain 创建Exposed实例抛出。

这对我来说很合理。

但在第二种情况下,appDomain.CreateInstanceAndUnwrap(...)经过得很好,我可以没有问题调用检索对象上的'SaySomething()'方法。例外

的方法 'SaySomethingDifferent' 没有在接口/类型发现 'IExposedIface.IExposedIface,IExposedIface,版本= 2.0.0.0,文化=中性公钥=空'。

只有当我实际拨打电话号码为SaySomethingDifferent()Consumer

我很惊讶,在这第二种情况下,CLR让我走了这么远......有人可以解释为什么这是可能的吗?

回答

0
  1. 案例#1意味着Exposed.dll是对错误的版本IExposedIface.dll的结合 - 元数据加载器能加载组件时,因为它发现一个未实现接口的方法来检测这一点。

  2. 案例#2(可能)意味着除了每个Exposed.dll之外,您还有每个IExposedIface.dll的正确版本,因此每个程序集都可以在其自己的AppDomain中加载。然而,AppDomain A的接口与AppDomain B的接口不同,当调用实际穿过AppDomain边界时,这只是一个问题。

我建议不要尝试那些二进制兼容游戏和宁做正确的版本(即创建一个新的方法新的接口,从旧的接口继承,所以IExposedIface.dll的新版本是真正向后兼容)。还有其他的是真的很难调试,因为如果你可以意外地加载版本的IExposedIface.dll,如果它们可以到达窗口,然后你有两个版本的AppDomain类型导致没有结束的麻烦;)