繁体   English   中英

在MEF合成期间处理ReflectionTypeLoadException

[英]Handle ReflectionTypeLoadException during MEF composition

我在MEF中使用DirectoryCatalog来满足我的应用程序中的导入。 但是,当我尝试编写目录时,目录中有时会出现模糊的程序集导致ReflectionTypeLoadException

我知道我可以通过使用单独的目录或使用DirectoryCatalog上的搜索过滤器来绕过它,但我想要一种更通用的方法来解决问题。 有什么方法可以处理异常并允许组合继续吗? 还是有另一个更通用的解决方案吗?

为了避免其他人编写他们自己的SafeDirectoryCatalog实现,这是我根据Wim Coenen的建议提出的:

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; }
    }
}

DirectoryCatalog已经有代码来捕获ReflectionTypeLoadException并忽略这些程序集。 不幸的是,正如我所报告的那样 ,仅仅创建AssemblyCatalog还不会触发异常,因此代码不起作用。

实际上,第一次调用AssemblyCatalog.Parts触发异常。

而不是使用MEF的DirectoryCatalog ,您必须自己完成:

  • 扫描目录以查看程序集
  • 加载每个程序集并为其创建AssemblyCatalog
  • 调用AssemblyCatalog.Parts.ToArray()来强制异常,并捕获它
  • 使用AggregateCatalog聚合所有好的目录

我是从我正在编写的API中执行此操作,而SafeDirectoryCatalog不会记录与来自不同程序集的单个导入匹配的多个导出。 MEF调试通常通过调试器和TraceListener完成。 我已经使用过Log4Net,我不希望有人需要在配置文件中添加另一个条目以支持日志记录。 http://blogs.msdn.com/b/dsplaisted/archive/2010/07/13/how-to-debug-and-diagnose-mef-failures.aspx我想出了:

    // 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);
        }
    }  

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM