MissingMethodException после извлечения базового интерфейса - PullRequest
1 голос
/ 08 марта 2019

Я разделил интерфейс внутри библиотеки пакета Nuget на более простой базовый интерфейс (без одного свойства из оригинала) и сделал исходный код производным от нового базового интерфейса.

Инстанцирование в потребляющих приложениях происходит через Managed Extensibility Framework (MEF), используя внедрение свойств с атрибутами [Import] и реализации с [Export(typeof(IFooConfigurations))]

Это не должно быть серьезным изменением для приложений, использующих старый интерфейс и реализацию. Но в некоторых случаях загружаются разные библиотеки, которые используют старые версии интерфейса и реализации. Это приводит к MissingMethodExceptions во время выполнения, говоря, что метод или свойство (метод get) не существует - например, свойство списка Configurations в примере.

Старый

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", решило проблему. Возможно, старые приложения и библиотеки, работающие с оригинальным интерфейсом, не могли разрешить унаследованные элементы как части оригинального интерфейса. Тем не менее, явные реализации и макеты могут быть неприятны с этим. Проверка еще не завершена.

1 Ответ

1 голос
/ 11 марта 2019

Элементы интерфейса, унаследованные от другого интерфейса, не эквивалентны элементам, которые определены в самом интерфейсе. Таким образом, перемещение членов в базовый интерфейс и наследование от него является серьезным изменением. Чтобы быть совместимыми с нисходящим потоком, члены интерфейса также должны быть определены сами по себе как «новые» (в C #).

Я подтвердил это с помощью простой тестовой программы, ссылающейся на разные сборки библиотек DLL с оригинальным единым интерфейсом, на разделение и на другую с разделением и дублированием «новых» членов. Так что это не проблема MEF.

К сожалению, эта проблема возникает только во время выполнения, после того, как выпуск пакета nuget уже собран.

...