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
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
.
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
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>();
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