Uchwyt ReflectionTypeLoadException podczas składu MEF
Używam DirectoryCatalog
W MEF, aby zaspokoić import w moim wniosku. Jednak czasami w katalogu są ukryte zespoły, które powodują ReflectionTypeLoadException
, gdy próbuję skomponować katalog.
Wiem, że mogę go obejść używając oddzielnego katalogu lub używając filtra wyszukiwania na DirectoryCatalog
, ale chcę bardziej ogólnego sposobu rozwiązania problemu. Czy mogę jakoś poradzić sobie z wyjątkiem i zezwolić na kontynuację kompozycji? A może jest inne bardziej ogólne rozwiązanie?
3 answers
DirectoryCatalog
ma już kod do przechwytywania ReflectionTypeLoadException
i ignorowania tych zestawów. Niestety, jak zgłosiłem , samo utworzenie AssemblyCatalog
nie spowoduje jeszcze wywołania wyjątku, aby kod nie działał.
Wyjątek jest faktycznie wyzwalany przez pierwsze wywołanie AssemblyCatalog.Parts
.
Zamiast używać DirectoryCatalog
z MEF, będziesz musiał zrobić to sam:
- skanowanie katalogu w poszukiwaniu zestawów
- załaduj każdy zespół i utwórz
AssemblyCatalog
dla niego - invoke
AssemblyCatalog.Parts.ToArray()
aby wymusić wyjątek i złapać go - zestawiamy wszystkie dobre katalogi z
AggregateCatalog
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:27:51
Aby uchronić innych przed napisaniem własnej implementacji SafeDirectoryCatalog, oto ta, którą wymyśliłem na podstawie sugestii Wima Coenena:
public class SafeDirectoryCatalog : ComposablePartCatalog
{
private readonly AggregateCatalog _catalog;
public SafeDirectoryCatalog(string directory)
{
var files = Directory.EnumerateFiles(directory, "*.dll", SearchOption.AllDirectories);
_catalog = new AggregateCatalog();
foreach (var file in files)
{
try
{
var asmCat = new AssemblyCatalog(file);
//Force MEF to load the plugin and figure out if there are any exports
// good assemblies will not throw the RTLE exception and can be added to the catalog
if (asmCat.Parts.ToList().Count > 0)
_catalog.Catalogs.Add(asmCat);
}
catch (ReflectionTypeLoadException)
{
}
catch (BadImageFormatException)
{
}
}
}
public override IQueryable<ComposablePartDefinition> Parts
{
get { return _catalog.Parts; }
}
}
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
2014-07-09 22:34:11
Robiłem to z API, które pisałem i SafeDirectoryCatalog nie zapisywał wielu eksportów pasujących do pojedynczego importu z różnych zestawów. Debugowanie MEF odbywa się zazwyczaj za pomocą debuggera i TraceListener. Używałem już Log4Net i nie chciałem, aby ktoś musiał dodać kolejny wpis do pliku konfiguracyjnego tylko po to, aby wspierać logowanie. http://blogs.msdn.com/b/dsplaisted/archive/2010/07/13/how-to-debug-and-diagnose-mef-failures.aspx{[3]wymyśliłem:
// I don't want people to have to add configuration information to get this logging.
// I know this brittle, but don't judge... please. It makes consuing the api so much
// easier.
private static void EnsureLog4NetListener()
{
try
{
Assembly compositionAssembly = Assembly.GetAssembly(typeof (CompositionContainer));
Type compSource = compositionAssembly.GetType("System.ComponentModel.Composition.Diagnostics.CompositionTraceSource");
PropertyInfo canWriteErrorProp = compSource.GetProperty("CanWriteError");
canWriteErrorProp.GetGetMethod().Invoke(null,
BindingFlags.Public | BindingFlags.NonPublic |
BindingFlags.Static, null, null,
null);
Type traceSourceTraceWriterType =
compositionAssembly.GetType(
"System.ComponentModel.Composition.Diagnostics.TraceSourceTraceWriter");
TraceSource traceSource = (TraceSource)traceSourceTraceWriterType.GetField("Source",
BindingFlags.Public |
BindingFlags.NonPublic |
BindingFlags.Static).GetValue(null);
traceSource.Listeners.Add(new Log4NetTraceListener(logger));
}
catch (Exception e)
{
logger.Value.Error("Cannot hook MEF compisition listener. Composition errors may be swallowed.", e);
}
}
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-05-26 22:17:56