【问题标题】:MEF load plugin from directoryMEF 从目录加载插件
【发布时间】:2012-06-14 18:18:54
【问题描述】:

我与 MEF 合作,我正在寻找如何通过 MEF 找到插件的另一种方式更改插件位置的 url,我想更改此行

Assembly.LoadFrom(@"C:\julia\project\project.Plugin.Nav\bin\Debug\NavPlugin.dll")));

我想删除这个网址,因为我需要在另一台机器上部署我的应用程序

这是我的功能:

public void AssembleCalculatorComponents()
{
   try
   {
       //var catalog = new AssemblyCatalog(Assembly.GetExecutingAssembly());
       //var container = new CompositionContainer(catalog);
       //container.ComposeParts(this);
       var catalog = new AggregateCatalog();

       catalog.Catalogs.Add(new AssemblyCatalog(Assembly.LoadFrom(@"C:\yosra\project\project.Plugin.Nav\bin\Debug\NavPlugin.dll")));
       var container = new CompositionContainer(catalog);

       container.ComposeParts(this);
    }
    catch (Exception ex)
    {
       throw ex;
    }
 }

你能帮帮我吗?

谢谢

【问题讨论】:

  • 附带说明:你不应该在你的 catch 块中使用throw ex; (这会“破坏”堆栈跟踪,即你将无法真正知道异常实际发生在哪里) .如果您想重新抛出异常,只需使用throw;(无需再次指定异常) - 或者如果您根本没有对异常做任何事情,就不要捕获异常!

标签: c# location mef .net-assembly


【解决方案1】:

您可以使用 DirectoryCatalog 类让 MEF 扫描特定目录以查找满足您的导入的程序集。

var catalog = new AggregateCatalog();
catalog.Catalogs.Add(new DirectoryCatalog("."));
var container = new CompositionContainer(catalog);

上面将添加 AppDomain 用于定位程序集的基本目录(通常是包含可执行文件的目录,除非配置更改)到聚合目录。您可能还想添加当前正在执行的程序集,但这不是必需的。

var catalog = new AggregateCatalog();
catalog.Catalogs.Add(new AssemblyCatalog(Assembly.GetExecutingAssembly()));
catalog.Catalogs.Add(new DirectoryCatalog("."));
var container = new CompositionContainer(catalog);

有关 MSDN for DirectoryCatalog 的更多信息:http://msdn.microsoft.com/en-us/library/system.componentmodel.composition.hosting.directorycatalog.aspx

【讨论】:

  • 感谢您的回复,我更改了此代码var catalog =new AggregateCatalog(); catalog.Catalogs.Add(new AssemblyCatalog(Assembly.GetExecutingAssembly())); catalog.Catalogs.Add(new DirectoryCatalog(@"./plugins")); var container = new CompositionContainer(catalog); 但不适用于我,请您为我解释更多
【解决方案2】:

再次您好,感谢您的回复,所以我的问题是直接加载插件,所以我创建了一个目录并将我的插件放在这个文件夹中,所以我找到了这个解决方案

public void AssembleCalculatorComponents()
        {


            string path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Plugins");
            Console.WriteLine(path);
            //Check the directory exists
            if (!Directory.Exists(path))
            {
                Directory.CreateDirectory(path);
            }
            Console.WriteLine(path);
            string assemblyName = Assembly.GetEntryAssembly().FullName;
            Console.WriteLine(assemblyName);
            //Create an assembly catalog of the assemblies with exports
            var catalog = new AggregateCatalog(
                new AssemblyCatalog(Assembly.GetExecutingAssembly().Location),
                new AssemblyCatalog(Assembly.Load(assemblyName)),
                new DirectoryCatalog(path, "*.dll"));

            //Create a composition container
            var container = new CompositionContainer(catalog);
            container.ComposeParts(this);

这是我的解决方案,为所有人着想

【讨论】:

    【解决方案3】:

    两个选项。

    1. 使用当前目录作为插件的根目录。 Environment.CurrentDirectory 应该为您指明正确的方向。
    2. 使用 app.config 指定要存储插件的目录。

    【讨论】:

      【解决方案4】:

      如果您的方法知道要实例化的类型,您可以使用TypeAssembly 属性,这是my *Domain* 库的典型属性;否则,您可以使用Assembly.GetExecutingAssembly()。我不是特别喜欢GetExecutingAssembly()GetCallingAssembly()……:

        public void AssembleCalculatorComponents() {
           try {
              var asmCatalog = new AssemblyCatalog(Assembly.GetExecutingAssembly());
           // OR
              asmCatalog = new AssemblyCatalog(typeof(TObject).Assembly); // replace TObject with object's actual type
              var aggregateCatalog = new AggregateCatalog(asmCatalog);
              // 
              AddDirectoryCatalogs(aggregateCatalog.Catalogs));
              var container = new CompositionContainer(catalog);
      
              // assuming this class has the member(s) to be composed.
              container.ComposeParts(this);
           } catch (Exception ex) {
              throw ex;
           }
        } 
      

      除此之外,您还可以添加 DirectoryCatalogs - 通过 app.config 文件、序列化的目录列表等。不过,您可以在 app.config 中指定一个默认目录 - 这是我推荐的。然后,假设您使用的是Settings

      private readonly Settings settings = Settings.Default;
      
      void AddDirectoryCatalogs(ICollection<ComposablePartCatalog> Catalogs agrCatalogs ) {
          agrCatalogs.Add(new DirectoryCatalog(settings.DefaultPath, settings.DefaultPattern));
          // add more directory catalogs
      }
      

      虽然使用 "." 作为搜索路径是执行程序集目录的合法快捷方式,但请记住,将搜索所有程序集以查找满足部分 - 即匹配 Import/Export 对象。我建议使用特定模式。 Microsoft 的示例并不以最佳 实践而闻名。如果您希望任何插件以 Plugin.dll 为后缀,请将其作为搜索模式的一部分。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多