如何在紧凑框架中从字节数组加载程序集

时间:2015-04-02 15:48:43

标签: c# compact-framework .net-assembly

我的遗留客户使用智能扫描仪和旧的Windows移动设备。结果,我在这些智能设备的紧凑框架中陷入困境。我正在编写一个类库,它将为扫描仪硬件的接口提供插件类型机制。我希望能够将来自扫描仪制造商的第三方程序集嵌入到插件DLL中作为嵌入式资源。我想这样做是为了避免在我的插件系统试图找到插件接口的实现时反映所有这些第三方DLL。漂亮的海峡前进。问题是,使用嵌入式资源,我可以获得程序集的字节,但紧凑框架中没有System.Reflection.Assembly.LoadAssembly(byte[])。仅限LoadAssembly(AssemblyName)LoadAssembly(String)。如何在运行时从嵌入式资源加载这些程序集?

这就是我现在所拥有的:

    protected void LoadEmbeddedAssemblies()
    {
        Assembly asm = Assembly.GetCallingAssembly();
        foreach (string resName in asm.GetManifestResourceNames())
        {
            if (resName.EndsWith(".dll"))
            {
                try
                {
                    //this is an embedded assembly
                    using (Stream s = asm.GetManifestResourceStream(resName))
                    {
                        if (s.Length > Int32.MaxValue) throw new IOException("The assembly is to large");
                        byte[] bytes = new byte[s.Length];                            
                        s.Read(bytes, 0, Convert.ToInt32(s.Length));

                        //Assembly.Load(bytes) <- Compact Framework sucks
                    }
                }
                catch (Exception e)
                {
                    Log(new LogMessageRaisedEventArgs("AScannerBase", "LoadEmbeddedAssemblies", "Exception encountered while loading embedded assembly", e.Message));
                }
            }
        }
    }

3 个答案:

答案 0 :(得分:2)

Compact Framework不支持以这种方式加载程序集。由于应用程序运行的平台不太可能在给定设备上更改,只需确定第一次运行的设备类型并将适当的程序集提取到app文件夹,从加载器上的那一点就可以找到它们。 / p>

答案 1 :(得分:2)

出于几个原因,我不建议将供应商程序集嵌入您的程序集中。首先,并非所有设备供应商SDK都是纯粹的.NET,可以或应该在app文件夹中填充。许多需要运行它们的安装来放置标准dll,注册表项等。其次,您通过将每个供应商程序集嵌入到中间件中来增加组件的大小,并且假设您支持多个供应商,则大小可能会变得非常大。特别是如果设备已经在GAC中安装了扫描程序集,那么您将获得根本不需要的额外存储空间。

我使用并建议以下机制:

Application(s)......................................
   |                                               .
   V                                               .
Generic scanning abstraction lib                   . (Assembly.LoadFrom based
   A                                               .  upon convention or XML 
   |                                               .  configuration file)
Vendor Specific Implementation of abstraction <.....
   |                                               
   V                                               
Vendor SDK 

通过这种方式,您可以在CAB创建时设置“插件”,包括根据配置文件或其他命名约定动态加载它们的信息。应用程序确实知道或关心抽象的哪个实现被加载,只是它符合抽象。

答案 2 :(得分:0)

我看到两种可能的解决方案来支持来自一个应用程序的不同设备:

  1. 使用您的方法并嵌入所需的设备程序集,并且不支持System.Reflection.Assembly.LoadAssembly(byte []),首先将程序集保存到文件系统,然后加载它。这样你就拥有了一个包含所有不同运行时文件的大型应用程序,其中只保存了所需的运行时并从文件系统加载。

  2. 您使用类似PocketMEF的插件系统,并具有不同的子目录来加载供应商特定的程序集和本机DLL。根据供应商的不同,朗姆酒可以动态加载。

  3. 在这两种情况下,您都必须定义一个接口层并实现为不同供应商的SDK实现接口的类。

    有关如何使用PocketMEF进行硬件抽象的文章位于http://www.hjgode.de/wp/2012/02/16/mobile-development-compact-framework-managed-extension-framework-mef/

    使用pocketMEF的几个接口的另一个例子是https://github.com/hjgode/intermeccontrols/blob/master/DPAG7

    而且,cTacke是对的,大多数.NET供应商程序集需要额外的本机库(即Intermec Barcode Scanner .NET程序集需要本机DLL itcscan.dll)。有时这些预先安装在Windows mobile / CE设备上,有时需要先安装它们。安装可能意味着只复制DLL或(我不知道使用它的供应商),安装额外的COM接口等,需要在使用前先注册。