我将Nuget包库中的接口拆分为更简单的基本接口(原始接口中没有一个属性),并使原始接口从新的基本接口派生。
使用应用程序中的实例化是通过托管扩展性框架 (MEF) 进行的,使用具有[Import]
属性的属性注入,以及具有[Export(typeof(IFooConfigurations))]
对于使用旧接口和实现的应用程序,这不应该是一个重大更改。但在某些情况下,会加载不同的库,这些库使用旧的接口版本和实现。这会导致运行时出现 MissingMethodExceptions,表示方法或属性(get 方法)不存在 - 例如示例中的Configurations
list 属性。
老:
public interface IFooConfigurations
{
int ConfigurationsIdentifier { get; }
IReadOnlyList<Configuration> Configurations { get; }
}
新增功能:
public interface IBaseFooConfigurations
{
// without the ConfigurationsIdentifier
IReadOnlyList<Configuration> Configurations { get; }
}
public interface IFooConfigurations : IBaseFooConfigurations
{
int ConfigurationsIdentifier { get; }
// Configurations inherited from IBaseFooConfigurations
}
实现(未更改)
[Export(typeof(IFooConfigurations)]
public class FooConfigurations : IFooConfigurations
{
// implementations of ConfigurationsIdentifier and Configurations
}
用法(未更改),通过 MEF 解决
public class FooApplicationClass
{
[Import]
private IFooConfigurations ConfigurationsOwner { get; set; }
}
跟踪此错误并找到可能的原因非常困难,因为它不会在通常的开发环境中发生。
它是否是一种解决方案,即使用new
关键字复制所有旧属性和方法,这些属性和方法现在位于基本接口中,新版本的IFooConfigurations
接口中,同时仍然派生自新IBaseFooConfigurations
?
可能的解决方案?
public interface IFooConfigurations : IBaseFooConfigurations
{
int ConfigurationsIdentifier { get; }
new IReadOnlyList<Configuration> Configurations { get; }
}
编辑:似乎保留原始接口的成员,用"new"关键字隐藏继承的成员,解决了这个问题。使用原始接口的较旧应用程序和库可能无法将继承的成员解析为原始接口的一部分。但是,显式实现和模拟可能会带来麻烦。仍有测试要做。
从另一个接口继承的接口成员不等同于在接口本身中定义的成员。因此,将成员移动到基接口并从中继承是一项重大更改。为了向下兼容,接口的成员也必须在自身中定义为"new"(在 C# 中)。
我用一个简单的测试程序证实了这一点,引用了具有原始单个接口的不同 DLL 版本,拆分和另一个具有拆分和重复"新"成员的 DLL。所以这不是MEF的问题。
遗憾的是,此问题仅在运行时发生,在已生成 nuget 包的版本之后。