在目录刷新期间遇到错误,不使用新的dll

ank*_*ush 6 .net c# mef

我正在尝试使用mef创建一个POC,我需要在一个准备好运行的项目中动态加载dll,为此我创建了一个控制台应用程序项目和一个类库

项目.

控制台应用程序项目的代码如下 -

namespace MefProjectExtension
{
    class Program
    {
        DirectoryCatalog catalog = new DirectoryCatalog(@"D:\MefDll", "*.dll");

        [Import("Method1", AllowDefault = true, AllowRecomposition = true)]
        public Func<string> method1;

        static void Main(string[] args)
        {
            AppDomainSetup asp = new AppDomainSetup();
            asp.ShadowCopyFiles = "true";

            AppDomain sp = AppDomain.CreateDomain("sp",null,asp);

            string exeassembly = Assembly.GetEntryAssembly().ToString();
            BaseClass p = (BaseClass)sp.CreateInstanceAndUnwrap(exeassembly, "MefProjectExtension.BaseClass");
            p.run();
        }
    }


    public class BaseClass : MarshalByRefObject
    {
        [Import("Method1",AllowDefault=true,AllowRecomposition=true)]
        public Func<string> method1;

        DirectoryCatalog catalog = new DirectoryCatalog(@"D:\MefDll", "*.dll");

        public void run()
        {
            FileSystemWatcher sw = new FileSystemWatcher(@"D:\MefDll", "*.dll");
            sw.NotifyFilter = NotifyFilters.CreationTime | NotifyFilters.Size;
            sw.Changed += onchanged;

            CompositionContainer container = new CompositionContainer(catalog);

            container.ComposeParts(this);

            Console.WriteLine(this.method1());

            sw.EnableRaisingEvents = true;

            Console.Read();
        }

        void onchanged(object sender, FileSystemEventArgs e)
        {
            catalog.Refresh();

            Console.WriteLine(this.method1());
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

满足进口的图书馆项目如下

namespace MefLibrary
{
    public interface IMethods
    {
         string Method1();  
    }

    public class CallMethods : IMethods
    {
        [Export("Method1")]
        public string Method1()
        {
            return "Third6Hello";
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

一旦我编译了库项目(MefLibrary)并将dll放在D:\ MefDll位置并第一次运行控制台应用程序,我将看到输出为

屏幕上的第三个6个

但是现在如果我更改了method1的实现并使其返回"third7hello"构建MEF库项目并替换为D:\ MefDll,而我的控制台应用程序正在运行onchanged处理程序,即使在调用目录刷新后在屏幕上打印 Third6hello 而不是third7hello

是否有人知道这是什么原因,如果是的话请帮忙.

Pan*_*nis 9

DirectoryCatalog.Refresh只会添加新的或删除现有的程序集.它不会更新程序集.一个粗略的解决方法是:

  1. 将更新的程序集移动到临时文件夹.
  2. 打电话DirectoryCatalog.Refresh.这将删除装配中包含的零件.
  3. 将组件移回监视文件夹
  4. 打电话DirectoryCatalog.Refresh.这将添加程序集中包含的更新部件.

注意:

  • 为此,您的"插件"程序集必须具有强大的命名不同的版本号(AssemblyVersionAttribute).这是必需的,因为当使用DirectoryCatalog.Refresh实际组件移除零件时将不会卸载.只能在卸载整个应用程序域时卸载程序集.因此,如果DirectoryCatalog.Refresh找到一个新的程序集,它将AssemblyCatalog使用程序集文件路径创建一个.AssemblyCatalog然后将调用Assembly.Load加载程序集.但是此方法不会加载AssemblyName.FullName与已加载的程序集具有相同的程序集.
  • 确保我提到的步骤不会触发另一个FileSystemWatcher.Changed事件.例如,您可以使用此方法.
  • 您的程序需要对监视文件夹具有写访问权限.如果您部署在%ProgramFiles%文件夹中,这可能是一个问题.
  • 如果您需要线程安全性,可以考虑使用CompositionOption.IsThreadSafe标志创建CompositionContainer .

正如我所提到的,这是一种解决方法.另一种方法是下载MEF的源代码并使用DirectoryCatalog.cs作为您自己的目录编目实现的指南.