0

I need to create new AppDomain and pass executing assembly to it, without any access to the assembly file itself. I have tried to use a binary serializer to transfer the loaded assembly, but it can't be done with the assembly existing only in memory.

The problem is that new AppDomain throws assembly load exception because there is no such a file in current directory.

Update: Even if I found a way to get the actual assembly byte array, saved it to disk and forced it to be loaded into new AppDomain - there is a casting error - I can't cast it from proxy type to actual class or interface.

Example project: https://drive.google.com/open?id=16z9nr8W5D8HjkBABgOCe5MIZKJSpFOul

Update 2: The example below is working when executed from assembly on the hard drive - there is no need to search the assembly file, and assembly FullName is enough in CreateInstanceFromAndUnwrap method. All errors occur when the assembly containing this code is loaded from byte array. Usage:

 public sealed class LoadDomain: IDisposable 
    {
        private AppDomain _domain;
        private IFacade _value;
        public IFacade Value
        {
            get
            {
                return _value;
            }
        }

        public void Dispose()
        {
            if (_domain != null)
            {
                AppDomain.Unload(_domain);

                _domain = null;
            }
        }
        public void Load(byte[] assemblyBytes,string assemblyPath,string assemmblyDir)
        {
            var domainSetup = new AppDomainSetup()
            {
                ShadowCopyDirectories = "true",
                ShadowCopyFiles = "true",
                ApplicationName = Assembly.GetExecutingAssembly().ManifestModule.ScopeName,
                DynamicBase = assemmblyDir,
                LoaderOptimization = LoaderOptimization.MultiDomainHost,
            };
            _domain = AppDomain.CreateDomain("Isolated:" + Guid.NewGuid(), null, domainSetup);
            // _domain.Load(assemblyBytes); not working
            // _domain.AssemblyResolve+=.. not working
             Type type = typeof(Facade);
            _value = (IFacade)_domain.CreateInstanceFromAndUnwrap(assemblyPath, type.FullName);
            //assemlby path working, but casting error : InvalidCastException
            //assembly FullName not working: FileNotFoundException
        }
    }
    public class Facade : MarshalByRefObject, IFacade
    {
        public void DoSomething()
        {
            MessageBox.Show("new domain");
        }
    }
kaqq
  • 345
  • 2
  • 7
  • You are going too fast, why is this assembly "existing only in memory"? Whatever you did to get it into memory, you'll have to do that again. – Hans Passant Jul 06 '18 at 16:32
  • I don't have any control over it. It is loaded by a separate application from a database. – kaqq Jul 06 '18 at 16:38
  • Yuck, what an awful idea. If you can't inspire it to do it again in the new AppDomain then you're up a creek without a paddle. – Hans Passant Jul 06 '18 at 16:44
  • Current AppDomain has this assembly already loaded - is there a way to reuse it in separate AppDomain? – kaqq Jul 06 '18 at 16:53
  • If you have the assembly in memory you could call [`Assembly.Load(byte[])`](https://msdn.microsoft.com/en-us/library/h538bck7.aspx). What is the concrete problem? – Oliver Jul 09 '18 at 11:44
  • @Oliver This won't work, I can't cast `AsemmblyA.TypeA` to `AsemmblyA.TypeA` if they are not loaded from the same file. _A second copy of the assembly is, indeed, being loaded into memory as it is. An instance of a type in the runtime is specific to the instance of the assembly loaded - so even if the same DLL file is loaded in a second time, the types are not considered to match._ (https://stackoverflow.com/questions/3655484/unable-to-cast-transparent-proxy-to-type-from-appdomain) I need to find a way to reuse the same assembly, or redirect assemblyresolve event. – kaqq Jul 09 '18 at 11:51
  • 1
    If you like to use types between two AppDomains you have to serialize the data in the first domain and deserialize it in the second domain as you would do it between two processes or you could try to derive your types from [`MarshalByRefObject`](https://stackoverflow.com/q/2206961/1838048). – Oliver Jul 09 '18 at 12:36
  • Serialization/MarshalByRef are the only ways for an object to cross AppDomains. @Oliver is completely correct here. – Tim Jul 13 '18 at 18:23
  • did you try to write an AssemblyResolve handler ? – ralf.w. Jul 14 '18 at 15:54
  • @ralf.w. Yes, Then I got class LoadDomain not found ex. Have also tried with assembly resolve delegate. I will try to make an example project. – kaqq Jul 16 '18 at 10:50
  • You are going to have to specify the exact use case you're trying to achieve or no one is going to be able to help you. I know, for example, the memory assembly can be saved to disk and loaded and used in the other AppDomain, but it sounds like you are trying to break the rules and make the types the same in both domains; you can't do that. You can only marshall across them. – Kit Jul 19 '18 at 22:20
  • @Kit That is what I'm trying to achieve - save assembly to a disk and load in another domain, then MarshalByRefObject a type across them. I have shown the example project. – kaqq Jul 20 '18 at 06:37

0 Answers0