System.Runtime.Serialization.SerializationException: Unable to find assembly MyAssembly

后端 未结 9 1814
-上瘾入骨i
-上瘾入骨i 2020-12-19 04:00

So I\'ve found a bunch of threads on this topic but I don\'t think I\'ve found one that applies yet.

Basically my .exe loads a .dll (MyAssembly) file which does the

9条回答
  •  不思量自难忘°
    2020-12-19 04:25

    I had a specific case of the SerializationException described by the OP, and found a relatively simple solution. In my case, I am implementing a DeepClone extension method using the BinaryFormatter technique. My application also makes use of plug-ins, assemblies that I load programmatically. I encountered the SerializationException when the BinaryFormatter.Deserialize method was called for an object whose class is contained in a plug-in.

    I find this very strange, because, by definition, the containing assembly is loaded into my AppDomain. (I couldn't call an extension method on the object if it wasn't!) Apparently, the BinaryFormatter does not check the AppDomain to resolve assemblies.

    Many of the solutions suggested here for solving this problem seem to involve hard coding the name of the assembly, or class, into a custom SerializationBinder. This is not useful, as I want my DeepClone method to be as generic as possible. My answer to this problem (shown below) hooks the AssemblyResolve event in the current AppDomain and then searches the AppDomain (using LINQ) for the requested assembly. No hard coded assembly or class names required.

    Here is the code:

    using System;
    using System.Collections.Generic;
    using System.IO;
    using System.Linq;
    using System.Reflection;
    using System.Runtime.Serialization.Formatters.Binary;
    using System.Runtime.Serialization;
    
    namespace StackOverflowDemo
    {
        public static class Extend
        {
            /// 
            /// Static initializer is used to register the Resolve Event Handler
            /// 
            static Extend()
            {
                AppDomain.CurrentDomain.AssemblyResolve += ResolveEventHandler;
            }
    
            /// 
            /// This resolver will find any Assembly that is already loaded into
            /// the current AppDomain and return it.
            /// 
            /// You would think this would not be necessary, but the 
            /// BinaryFormatter.Deserialize method apparently can not 
            /// find an assembly that has been loaded programmatically
            /// as a plug-in, and whose DLL does not reside in the same
            /// folder as the executable file.
            /// 
            /// 
            /// 
            /// 
            private static Assembly ResolveEventHandler( object sender, ResolveEventArgs args )
            {
                var assemblies = AppDomain.CurrentDomain.GetAssemblies();
                Assembly result = (from a in assemblies where args.Name.Equals(a.FullName) select a).FirstOrDefault();
                return result;
            }
    
    
            /// 
            /// Slow, and requires that the source be marked as [Serializable], but 
            /// clones *everything* and is not complicated.
            /// 
            /// Note that by itself, this method will fail if an attempt is made to
            /// create a deep copy of an object whose class is contained in an assembly
            /// that was loaded programmatically (i.e., loaded as a plug-in).
            /// 
            /// See https://stackoverflow.com/a/1213649
            /// 
            /// and https://stackoverflow.com/a/23017515
            /// 
            /// 
            /// 
            /// 
            public static T DeepClone( this T src )
            {
                if (!typeof(T).IsSerializable)
                {
                    throw new ArgumentException(string.Format("[Extend.DeepClone] Type '{0}' is not Serializable", typeof(T).Name));
                }
    
                if (Object.ReferenceEquals(src, null))
                {
                    return default(T);
                }
    
                using (Stream stream = new MemoryStream())
                {
                    IFormatter formatter = new BinaryFormatter();
                    formatter.Serialize(stream, src);
                    stream.Seek(0, SeekOrigin.Begin);
                    return (T)formatter.Deserialize(stream);
                }
            }
        }
    }
    

提交回复
热议问题