1

我正在开发一个应用程序,它使用 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);
}
4

2 回答 2

2

尝试使用AllowDefaultImport 属性的属性。

[Import(AllowDefault=true)]

从文档:

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

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

于 2013-11-15T09:48:48.723 回答
1

这是我为避免错误所做的。感谢@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);
        }
    }
}

}

于 2013-11-15T12:21:46.613 回答