期间目录刷新面对错误时,不使用新的DLL [英] Facing error during catalog refresh, the new dll is not used

查看:180
本文介绍了期间目录刷新面对错误时,不使用新的DLL的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想创建与MEF一个POC在那里我的要求加载DLL动态地在一切准备就绪正在运行的项目,为了这个,我已创建了一个控制台应用程序项目和一个类库

I am trying to create a POC with mef where i have the requirement to load dll dynamically in an all ready running project , for this i have created one console application project and a class Library

项目。

在code控制台应用程序项目如下 -

the code for console application project is as follows-

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

库项目满足进口看起来如下 -

the library project which satisfy import looks as follow-

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

    public class CallMethods : IMethods
    {
        [Export("Method1")]
        public string Method1()
        {
            return "Third6Hello";
        }
    }
}

有一次,我编译库项目(MefLibrary),并把DLL在D:\ Mef​​Dll位置和运行首次控制台应用程序,我会看到的。

once i compile the library project(MefLibrary) and put the dll in D:\MefDll location and run the console application for first time i will see the output as

Third6hello在屏幕上

但现在如果我改变方法1的执行,并使其返回third7helloMEF建立项目库并替换为D:\ Mef​​Dll,而我的控制台应用程序,即使调用目录刷新打印运行onChanged处理 Third6hello在屏幕上,而不是 third7hello

but now if i change the implementation of method1 and make it return "third7hello" build MEF Library project and replace at D:\MefDll while my console app is running the onchanged handler even after calling catalog refresh prints Third6hello on screen rather than third7hello

是否有人知道究竟是什么原因,如果是请大家帮忙。

Whether anyone knows what is the reason for this , if yes please help.

推荐答案

DirectoryCatalog.Refresh 只会增加新的或删除现有的组件。它不会更新组件。粗解决方法是:

DirectoryCatalog.Refresh will only add new or remove existing assemblies. It will not update an assembly. A crude workaround is:

  1. 将更新的组件到一个临时文件夹。
  2. 呼叫 DirectoryCatalog.Refresh 。这将删除包含在组件中的一部分(S)。
  3. 将装配回监视文件夹
  4. 呼叫 DirectoryCatalog.Refresh 。这将添加包含的组件更新的一部分(S)。
  1. Move the updated assembly to a temp folder.
  2. Call DirectoryCatalog.Refresh. This will remove the part(s) contained in the assembly.
  3. Move the assembly back to the watched folder
  4. Call DirectoryCatalog.Refresh. This will add the updated part(s) contained in the assembly.

注意:

  • 对于这个工作,你的插件组件必须强大的名为不同的版本号(<$ C C $> AssemblyVersionAttribute )。这是必要的,因为当部分使用 DirectoryCatalog.Refresh 的实际装配被删除将无法卸载。整个应用程序域被卸载时,组件只能被卸载。因此,如果 DirectoryCatalog.Refresh 找到一个新的组装这将创建一个 AssemblyCatalog 使用汇编文件路径。 AssemblyCatalog 将调用的Assembly.Load 加载程序集。但是,这种方法不会加载具有相同 AssemblyName.FullName 与已加载的程序集。
  • 组装
  • 确保我提到的步骤,也不会触发其他FileSystemWatcher.Changed事件。例如,你可以使用这种方法
  • 您的方案需要对监视文件夹的写权限。这可能是一个问题,如果你的%ProgramFiles%文件夹中进行部署。
  • 如果您需要线程安全的,你可以考虑创建CompositionContainer中使用 CompositionOption.IsThreadSafe 标记。
  • For this to work your "plugin" assemblies have to be strong named and with different version numbers (AssemblyVersionAttribute). This is needed because when parts are removed using the DirectoryCatalog.Refresh the actual assembly will not be unloaded. Assemblies can only be unloaded when the whole application domain is unloaded. So if DirectoryCatalog.Refresh finds a new assembly it will create an AssemblyCatalog using the assembly filepath. AssemblyCatalog will then call Assembly.Load to load the assembly. But this method will not load an assembly that has the same AssemblyName.FullName with an already loaded assembly.
  • Make sure that the steps I mention will not trigger another FileSystemWatcher.Changed event. For example you could use this approach.
  • Your program will need to have write access on the watched folder. This can be a problem if you deploy in the %ProgramFiles% folder.
  • If you need thread-safety you can consider creating your CompositionContainer with the CompositionOption.IsThreadSafe flag.

正如我所说,这是一个解决办法。另一种方法是下载 MEF的源$ C ​​$ C 并使用DirectoryCatalog的.cs作为方针,为自己的目录目录,执行

As I mentioned this is a workaround. Another approach would be to download MEF's source code and use DirectoryCatalog.cs as a guideline for your own directory catalog implementation.

这篇关于期间目录刷新面对错误时,不使用新的DLL的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆