Zizi
Zizi

Reputation: 59

NHibernate is unable to resolve classes in a dynamically loaded assembly loaded from a subdirectory

//Formatting is not properly done.

Using nopcommerce plugins written in nhibernate and .net core, each plugins contains its own entities directory, but when NHibernate configuration fails

var cfg = new Configuration();
cfg.Configure(CommonHelper.MapPath("~/App_Data/db/defauls.config"));
// error here
cfg.AddAssembly("plugins assembly name");

FileNotFoundException: Could not load file or assembly 'plugins assembly name' or one of its dependencies. The system cannot find the file specified.

System.Reflection.RuntimeAssembly._nLoad(AssemblyName fileName, string codeBase, Evidence assemblySecurity, RuntimeAssembly locationHint, ref StackCrawlMark stackMark, IntPtr pPrivHostBinder, bool throwOnFileNotFound, bool forIntrospection, bool suppressSecurityChecks) MappingException: persistent class "plugins assembly name.Entities.class name, plugins assembly name not found

NHibernate.Cfg.XmlHbmBinding.Binder.ClassForFullNameChecked(string fullName, string errorMessage) MappingException: Could not compile the mapping document: plugins assembly name.Entities.class name.hbm.xml

NHibernate.Cfg.Configuration.LogAndThrow(Exception exception)

Upvotes: 1

Views: 211

Answers (1)

Raju Paladiya
Raju Paladiya

Reputation: 818

Assume Plugin.Shop.dll is placed in root folder of plugin Plugin.Shop.Entities folder. From property select content type as Embedded Resource and give reference of this DLL and from property set it False to copy out folder.

This is EmbeddedAssembly.cs file

using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Security.Cryptography;

namespace Plugin.Shop.Entities
{
    public class EmbeddedAssembly
    {
        // Version 1.0

        static Dictionary<string, Assembly> dic = null;

        public static void Load(string embeddedResource, string fileName)
        {
            if (dic == null)
                dic = new Dictionary<string, Assembly>();

            byte[] ba = null;
            Assembly asm = null;
            Assembly curAsm = Assembly.GetExecutingAssembly();

            using (Stream stm = curAsm.GetManifestResourceStream(embeddedResource))
            {
                // Either the file is not existed or it is not mark as embedded resource
                if (stm == null)
                    throw new Exception(embeddedResource + " is not found in Embedded Resources.");

                // Get byte[] from the file from embedded resource
                ba = new byte[(int)stm.Length];
                stm.Read(ba, 0, (int)stm.Length);
                try
                {
                    asm = Assembly.Load(ba);

                    // Add the assembly/dll into dictionary
                    dic.Add(asm.FullName, asm);
                    return;
                }
                catch
                {
                    // Purposely do nothing
                    // Unmanaged dll or assembly cannot be loaded directly from byte[]
                    // Let the process fall through for next part
                }
            }

            bool fileOk = false;
            string tempFile = "";

            using (SHA1CryptoServiceProvider sha1 = new SHA1CryptoServiceProvider())
            {
                string fileHash = BitConverter.ToString(sha1.ComputeHash(ba)).Replace("-", string.Empty); ;

                tempFile = Path.GetTempPath() + fileName;

                if (File.Exists(tempFile))
                {
                    byte[] bb = File.ReadAllBytes(tempFile);
                    string fileHash2 = BitConverter.ToString(sha1.ComputeHash(bb)).Replace("-", string.Empty);

                    if (fileHash == fileHash2)
                    {
                        fileOk = true;
                    }
                    else
                    {
                        fileOk = false;
                    }
                }
                else
                {
                    fileOk = false;
                }
            }

            if (!fileOk)
            {
                System.IO.File.WriteAllBytes(tempFile, ba);
            }

            asm = Assembly.LoadFile(tempFile);

            dic.Add(asm.FullName, asm);
        }

        public static Assembly Get(string assemblyFullName)
        {
            if (dic == null || dic.Count == 0)
                return null;

            if (dic.ContainsKey(assemblyFullName))
                return dic[assemblyFullName];

            return null;
        }
    }
}

This is Dependency Register File

using Autofac;
using Autofac.Core;
using Nop.Core.Configuration;
using Nop.Core.Data;
using Nop.Core.Infrastructure;
using Nop.Core.Infrastructure.DependencyManagement;
using Nop.Data;
using Nop.Web.Framework.Mvc;
using System;
using System.Reflection;

namespace Plugin.Shop.Entities.Infrastructure
{
    /// <summary>
    /// Dependency registrar
    /// </summary>
    public class DependencyRegistrar : IDependencyRegistrar
    {       
        public virtual void Register(ContainerBuilder builder, ITypeFinder typeFinder, NopConfig config)
        {
            builder.RegisterType<NameService>().As<INameService>().InstancePerLifetimeScope();

            string codeDll = "Plugin.Shop.Entities.Plugin.Shop.dll";
            EmbeddedAssembly.Load(codeDll, "Plugin.Shop.dll");

            AppDomain.CurrentDomain.AssemblyResolve += CurrentDomain_AssemblyResolve;
        }

        private Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
        {
            return EmbeddedAssembly.Get(args.Name);
        }

        public int Order
        {
            get { return 1; }
        }
    }
}

Upvotes: 0

Related Questions