【问题标题】:How to degrade gracefully when MEF component dependencies not installed?未安装 MEF 组件依赖项时如何优雅降级?
【发布时间】:2013-11-15 09:34:43
【问题描述】:

我正在开发一个应用程序,它使用 MEF 将接口插入到外部设备(I/O 设备、示波器、波形发生器等)。大多数这些接口都需要 DLL 来访问设备,如果可能,我会将这些 DLL 打包到包含插件的项目中。

应用程序使用ImportMany 加载所有实现插件接口的类。然后用户可以选择需要哪些接口。

我有一个给我带来困难的界面。我无法识别所有依赖项,当我在另一个工作站上启动应用程序时,我得到一个未解决的依赖项错误。我敢肯定,当我安装所有驱动程序并支持 DLL 时,它会正常工作。

但是,并非所有用户都需要使用此特定界面,我不想在所有工作站上安装所有驱动程序。我正在寻找一种在某些 MEF 插件无法加载时优雅降级的方法。一条日志消息足以说明无法加载界面。只有那些试图使用接口函数的人应该得到错误。

这是我的加载器代码:

try
{
    var catalog = new AggregateCatalog();
    var container = new CompositionContainer(catalog);
    var batch = new CompositionBatch();
    batch.AddPart(this);
    catalog.Catalogs.Add(new AssemblyCatalog(typeof (Pruef.Net.TgtManager.TargetManager).Assembly));
    container.Compose(batch);

    _targets = _targets.OrderBy(t => t.DisplayName);
}
catch (Exception x)
{
    log.Error(x);
}

【问题讨论】:

    标签: c# .net dll mef


    【解决方案1】:

    尝试使用 Import 属性的AllowDefault 属性。

    [Import(AllowDefault=true)]
    

    来自文档:

    获取或设置一个值,该值指示属性、字段或 导出时,参数将设置为其类型的默认值 容器中不存在合约名称。

    注意:如果您的插件在创建时抛出异常,您的应用程序仍然会失败。仍应处理导致缺少驱动程序的异常。

    【讨论】:

    • +1 感谢您的提示。实际上,我使用的是ImportMany,但我看到有一个延迟加载选项(msdn.microsoft.com/en-us/library/…)。我现在去看看。 [从黑森林到我的家乡-索顿的问候:-)]
    • @paul 延迟初始化是一个很好的呼喊。它将允许您很好地捕获创建异常!
    • 重新注意。我想这正在发生。由于缺少依赖项,类加载总是会失败:-(
    【解决方案2】:

    这是我为避免错误所做的。感谢@Gusdor 为我指明了正确的方向。延迟加载似乎是要走的路。

    public class TargetManager
    {
        private static log4net.ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
    
        [ImportMany(typeof(Pruef.Net.Contracts.ITarget))]
        private IEnumerable<Lazy<Pruef.Net.Contracts.ITarget>> _targets;
    
        public IEnumerable<Pruef.Net.Contracts.ITarget> AvailableTargets
        {
            get;
            private set;
        }
    
        /// <summary>
        /// Load all known target definitions
        /// </summary>
        public void Init()
        {
            try
            {
                var catalog = new AggregateCatalog();
                var container = new CompositionContainer(catalog);
                var batch = new CompositionBatch();
                batch.AddPart(this);
                catalog.Catalogs.Add(new AssemblyCatalog(typeof(Pruef.Net.TgtManager.TargetManager).Assembly));
                container.Compose(batch);
    
                List<ITarget> result = new List<ITarget>();
                foreach (Lazy<ITarget> t in _targets)
                {
                    try
                    {
                        result.Add(t.Value);
                    }
                    catch (Exception x)
                    {
                        // could not load plugin
                        // log error and continue
                        log.Error(x);
                    }
                }
                result = result.OrderBy(t => t.DisplayName).ToList();
                AvailableTargets = result;
            }
            catch (Exception x)
            {
                log.Error(x);
            }
        }
    }
    

    }

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2010-10-07
      • 1970-01-01
      • 2015-01-24
      • 2011-08-29
      • 1970-01-01
      • 2016-03-14
      • 2016-07-29
      相关资源
      最近更新 更多