MEF: "nie można załadować jednego lub więcej żądanych typów. Pobierz plik LoaderExceptions, aby uzyskać więcej informacji"

Scenariusz: używam Managed Extensibility Framework do ładowania wtyczek (eksportu) w czasie wykonywania na podstawie umowy interfejsu zdefiniowanej w oddzielnej dll. W moim rozwiązaniu Visual Studio mam 3 różne projekty: aplikację hosta, bibliotekę klasową (definiującą interfejs - "Iplugin") i inną bibliotekę klasową implementującą interfejs (eksport - " MyPlugin.dll").

Host szuka eksportu we własnym katalogu głównym, więc podczas testowania buduję całe rozwiązanie i kopiuję Plugin.dll z biblioteki klas plugin bin/release folderu do katalogu debug Hosta tak, że Katalog hosta znajdzie go i będzie mógł dodać go do komponentu. Plugin.dll nie jest automatycznie kopiowany po każdej przebudowie, więc robię to ręcznie za każdym razem, gdy dokonałem zmian w umowie/realizacji.

Jednak kilka razy uruchomiłem aplikację hosta bez skopiowania (zaktualizowanej) wtyczki.najpierw dll, i wyrzucił wyjątek podczas skład:

Unable to load one or more of the requested types. Retrieve the LoaderExceptions for more information

Wynika to oczywiście z faktu, że wtyczka.dll próbuje zaimportować z implementuje inną wersję IPlugin, gdzie sygnatury właściwości/metody nie pasują. Chociaż łatwo jest tego uniknąć w kontrolowanym i monitorowanym środowisku, po prostu unikając (duh) przestarzałych implementacji IPlugin w folderze wtyczek, nie mogę polegać na takich założeniach w środowisku produkcyjnym, gdzie starsze wtyczki mogą być / align = "left" /

Problem polega na tym, że ten wyjątek skutecznie blokuje całą akcję Compose i eksport nie jest importowany. Wolałbym, aby niedopasowane implementacje IPlugin były po prostu ignorowane, tak aby inne eksportowanie w katalogach, implementujące poprawną wersję IPlugin, nadal było importowane.

Czy jest jakiś sposób, aby to osiągnąć? Myślę o jednej z kilku możliwych opcji:
  • jest flaga do Ustawienia na CompositionContainer ("ignoruj nieudane importowanie") przed lub podczas wywoływania Compose
  • istnieje podobna Flaga do określenia atrybutu <ImportMany()>
  • istnieje sposób, aby "podłączyć" się do procesu iteracji leżącego u podstaw metody Compose () i być w stanie poradzić sobie z każdym (nieudanym) importem z osobna
  • używanie silnego podpisywania nazw, aby jakoś szukać tylko importu implementującego bieżącą wersję IPlugin
Pomysły?
Author: Chris Snow, 2010-10-26

3 answers

Napotkałem również podobny problem.

Jeśli jesteś pewien, że chcesz zignorować takie "złe" zespoły, rozwiązaniem jest wywołanie AssemblyCatalog.Części.ToArray () zaraz po utworzeniu każdego katalogu złożenia. Spowoduje to uruchomienie ReflectionTypeLoadException, o którym wspomniałeś. Następnie masz szansę złapać wyjątek i zignorować zły montaż.

Kiedy utworzysz AssemblyCatalog obiekty dla wszystkich "dobrych" zestawów, możesz je połączyć w AggregateCatalog i przekazać je do konstruktor CompositionContainer.

 15
Author: Wim Coenen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-08-23 15:35:54

Ten problem może być spowodowany przez kilka czynników (wyjątki na załadowanych złożeniach), jak mówi wyjątek, spójrz na ExceptionLoader, aby (miejmy nadzieję) dowiedzieć się czegoś

Kolejny problem / rozwiązanie, które znalazłem, jest przy użyciu DirectoryCatalog , Jeśli nie podasz drugiego parametru "searchPattern", MEF załaduje wszystkie biblioteki DLL w tym folderze (w tym strony trzeciej), i zacząć szukać typów eksportu, które mogą również powodować ten problem, rozwiązaniem jest mieć nazwa konwencyjna dla wszystkich zestawów, które eksportują typy i określa, że w Konstruktorze DirectoryCatalog używam * _Plugin.dll, w ten sposób MEF załaduje tylko zespoły, które zawierają wyeksportowane typy

W moim przypadku MEF ładował bibliotekę dll NHibernate i wyrzucał jakiś błąd w wersji assembly na LoaderException( ten błąd może wystąpić w każdym z bibliotek DLL w katalogu), takie podejście rozwiązało problem

 7
Author: BlackTigerX,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-12-02 00:31:34

Oto przykład wyżej wymienionych metod:

var di = new DirectoryInfo(Server.MapPath("../../bin/"));

        if (!di.Exists) throw new Exception("Folder not exists: " + di.FullName);

        var dlls = di.GetFileSystemInfos("*.dll");
        AggregateCatalog agc = new AggregateCatalog(); 

        foreach (var fi in dlls)
        {
            try
            {
                var ac = new AssemblyCatalog(Assembly.LoadFile(fi.FullName));
                var parts = ac.Parts.ToArray(); // throws ReflectionTypeLoadException 
                agc.Catalogs.Add(ac);
            }
            catch (ReflectionTypeLoadException ex)
            {
                Elmah.ErrorSignal.FromCurrentContext().Raise(ex);
            }
        }

        CompositionContainer cc = new CompositionContainer(agc);

        _providers = cc.GetExports<IDataExchangeProvider>();
 7
Author: Jan Remunda,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-10-17 19:03:52