How to load an assembly from byte array in compact framework

时间秒杀一切 提交于 2019-12-10 21:16:37

问题


I have legacy clients who use smart scanners with old windows mobile on them. As a result, I'm stuck developing in the compact framework for these smart devices. I am in the process of writing a class library which will provide a plugin type mechanism for an interface to the scanner hardware. I would like to be able to embed the third party assemblies from the scanner manufacturer as an embedded resource in the plugins DLL. I want to do this to avoid having to reflect over all of those third party DLL's when my plugin system is trying to find implementations of the interface for the plugins. Pretty strait forward. The issue is that with the embedded resource, I can get the bytes for the assembly, but System.Reflection.Assembly.LoadAssembly(byte[]) is not available in the compact framework. Only LoadAssembly(AssemblyName) and LoadAssembly(String). How can I load these assemblies at runtime from an embedded resource?

This is what I have now:

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

回答1:


The Compact Framework doesn't support loading an assembly that way. Since the platforms the app is running on is unlikely to ever change on a given device, just determine the device type of the first run and extract the appropriate assemblies to the app folder, from that point on the loader will find them for you.




回答2:


I don't suggest embedding the vendor assemblies in yours for a couple of reasons. First, not all device vendor SDKs are pure .NET that can or should be plopped down in the app folder. Many require their install to be run to put standard dlls, registry entries, and the like in place. Secondly, you are increasing the size of your component by embedding each vendors assemblies in your middleware and, assuming that you are supporting multiple vendors, the size could get quite large. Especially if the device already has the scanning Assemblies in the GAC, you are taking extra storage you didn't need to at all.

I use, and suggest, the following mechanism:

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 

In this way, you setup your "plugins" at CAB creation time including the information to dynamically load them based on a config file or other naming convention. The app does know or care which implementation of the abstraction gets loaded, only that it conforms to the abstraction.




回答3:


I see two possible solutions to support different devices from one application:

  1. you use your approach and embedd the needed assembly of a device and, as System.Reflection.Assembly.LoadAssembly(byte[]) is not supported, save the assembly first to file system and then load it. that way you have a large aplication with all kind of different runtime files in, where only the needed runtimes are saved and load to/from file system.

  2. You use a plugin system like PocketMEF and have different subdirs to load the vendor specific assemblies and native DLLs. The rumtimes can be load dynamically depending on the vendor.

In both cases you have to define an interface layer and implement classes that implement the interface for the different vendor's SDKs.

An article about how to use PocketMEF for hardware abstracion is at http://www.hjgode.de/wp/2012/02/16/mobile-development-compact-framework-managed-extension-framework-mef/

Another example with several interfaces using pocketMEF is at https://github.com/hjgode/intermeccontrols/blob/master/DPAG7

And, cTacke is right, most .NET vendor assemblies need additional native libraries (ie Intermec Barcode Scanner .NET assembly needs a native DLL itcscan.dll). Sometimes these are pre-installed on windows mobile/CE devices, sometimes they need to be installed first. Installation may mean to copy DLLs only or (I did not know of a vendor using that), install additional COM interface etc, that need to be registered first before use.



来源:https://stackoverflow.com/questions/29417154/how-to-load-an-assembly-from-byte-array-in-compact-framework

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!