我将一个Nuget包库中的接口拆分为一个更简单的基接口(没有原始的一个属性),并使原始派生自新的基接口。
消费应用程序中的实例化通过Managed Extensibility Framework(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; }
}
跟踪此错误并找到可能的原因非常困难,因为它不会出现在通常的开发环境中。
可能是一个解决方案,在IFooConfigurations
界面的新版本中使用new
关键字复制现在在基本界面中的所有旧属性和方法,同时仍然从新的IBaseFooConfigurations
派生?
可能的方案?
public interface IFooConfigurations : IBaseFooConfigurations
{
int ConfigurationsIdentifier { get; }
new IReadOnlyList<Configuration> Configurations { get; }
}
编辑:似乎保留原始界面的成员,用“new”关键字隐藏继承的成员,解决了问题。可能是,使用原始接口的旧应用程序和库无法将继承的成员解析为原始接口的一部分。但是,显式实现和模拟可能会带来麻烦。仍有测试要做。
从另一个接口继承的接口成员不等同于在接口本身中定义的成员。因此,将成员移动到基接口并从中继承,是一个重大变化。要向下兼容,接口的成员也必须自己定义为“new”(在C#中)。
我用一个简单的测试程序证实了这一点,用原始的单一界面引用了不同版本的DLL,拆分了另一个与拆分和重复的“新”成员。所以这不是MEF的问题。
不幸的是,这个问题只发生在运行时,在已经构建了nuget包的发布之后。