LoaderOptimization.MultiDomain incompatible with generics?  
Author Message
Alain B-H





PostPosted: Common Language Runtime, LoaderOptimization.MultiDomain incompatible with generics? Top

Hello,

I experience a  FileLoadException (Loading this assembly would produce a different grant set from other instances. (Exception from HRESULT: 0x80131401)) very difficult to understand.

I have done a dummy project to reproduce it. It is at the end.
 
The conjunction of the following things leads to this problem:
- 2 AppDomain application (composed with only one exe in my dummy application)
- LoaderOptimization.MultiDomain for the second AppDomain
- MarshalByRefObject created with CreateInstanceAndUnwrap
- Trying to access remotely to a property of the MBR that itself contains a generic List instantiated with a custom type (e. g. not a primitive one)

My understanding of the issue is that the instantiated generic type is not shared with all AppDomains, leading to a different grant set.

A note concerning MultiDomain explains that some issues can occur if you programmatically load assembly. I don't do that or maybe indirectly through the CreateInstanceAndUnwrap method.

Can somebody help me answering the following questions:
- How can I have a look (at runtime or with the de****) at the assembly grant set for each assembly in each AppDomain
- Is it a bug or do I have to make the difficult choice between using MultiDomain and using Generics (by design...)
- If MultiDomain does not work with cross AppDomain (CreateInstanceAndUnwrap) how can I benefit from this optimization
- Is it for a security reason that this message does not provide crucial information like the assembly concerned, the difference between grant set

Thanks for any answer,

Alain

Here is the code

Program.cs


using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Xml.Serialization;

namespace IssuesWithGenerics {

    class Program {

        static AppDomain CreateSubAppDomain(DirectoryInfo applicationDir,
                                            DirectoryInfo domainDir,
                                            FileInfo domainConfig) {

            AppDomain rootAppDomain = AppDomain.CurrentDomain;
            AppDomainSetup rootSetup = rootAppDomain.SetupInformation;
            AppDomainSetup subSetup = new AppDomainSetup();

            subSetup.ApplicationName = rootSetup.ApplicationName;
            subSetup.ApplicationBase = applicationDir.FullName;
            subSetup.ConfigurationFile = domainConfig.FullName;
            subSetup.PrivateBinPath = ".;.\\" + domainDir.Name;
            subSetup.LoaderOptimization = LoaderOptimization.MultiDomain;

            return AppDomain.CreateDomain(rootSetup.ApplicationName +
                                          ".SubAppDomain", null, subSetup);
        }

        static MbrFacade CreateMbrFacade(AppDomain ad) {

            Type t = typeof(MbrFacade);
            return (MbrFacade) ad.CreateInstanceAndUnwrap
                                      (t.Assembly.FullName, t.FullName);
        }

        [LoaderOptimization(LoaderOptimization.MultiDomain)]
        static void Main(string[] args) {

            DirectoryInfo appDir = new DirectoryInfo
                 (AppDomain.CurrentDomain.SetupInformation.ApplicationBase);
            DirectoryInfo domainDir = appDir.GetDirectories("SubAppDomain")[0];
            FileInfo domainConfig = domainDir.GetFiles("AppDomain.config")[0];

            AppDomain subAppDomain = CreateSubAppDomain
                                         (appDir, domainDir, domainConfig);
            ComponentRegistry cr = new ComponentRegistry();
            MbrFacade mf = CreateMbrFacade(subAppDomain);
            ILocalComponent lc = mf.Create(cr);
            cr.Register(lc.ComponentId, lc as MbrFacade);
            foreach (KeyValuePair<ComponentId, MbrFacade> kvp in cr) {
                 Console.WriteLine(kvp.Value.ComponentInfo);
            }
            Console.ReadLine();
        }
    }

    public class ComponentRegistry : MarshalByRefObject,
                                IEnumerable<KeyValuePair<ComponentId, MbrFacade>> {

        private Dictionary<ComponentId, MbrFacade> m_facades =
            new Dictionary<ComponentId, MbrFacade>();

        public void Register(ComponentId cid, MbrFacade mf) {
            m_facades.Add(cid, mf);
        }

         System.Collections.IEnumerator
                 System.Collections.IEnumerable.GetEnumerator() {
             return m_facades.GetEnumerator();
         }

         IEnumerator<KeyValuePair<ComponentId, MbrFacade>>
                 IEnumerable<KeyValuePair<ComponentId, MbrFacade>>
                      .GetEnumerator() {
             return m_facades.GetEnumerator();
         }
    }

    [XmlType]
    [Serializable]
    public class ComponentId {

        private string m_name;

        public ComponentId(string name) {
            m_name = name;
        }

        [XmlElement]
        public string Name {
            get {
                return m_name;
            }
            set {
                if (m_name == null) {
                    m_name = value;
                }
            }
        }
    }

    [XmlType]
    [Serializable]
    public class ComponentInfo {

        private List<ComponentId> m_componentIds;

        public ComponentInfo() {
            m_componentIds = new List<ComponentId>();
        }

        public List<ComponentId> ComponentIds {
            get {
                return m_componentIds;
            }
        }
    }

    public interface ILocalComponent {

        ComponentId ComponentId {
            get;
        }

        ComponentInfo ComponentInfo {
            get;
        }
    }

    public class MbrFacade : MarshalByRefObject, ILocalComponent {

        private ILocalComponent m_localComponent;

        public MbrFacade() {
        }

        public ILocalComponent Create(ComponentRegistry cr) {
             m_localComponent = new LocalComponent(new ComponentId("test"));
             return this;
        }

        public ComponentId ComponentId {
            get {
                return m_localComponent.ComponentId;
            }
        }

        public ComponentInfo ComponentInfo {
            get {
                return m_localComponent.ComponentInfo;
            }
        }

        public override object InitializeLifetimeService() {
            return null;
        }
    }

    public class LocalComponent : ILocalComponent {

        private ComponentInfo m_componentInfo;
        private ComponentId m_componentId;

        public LocalComponent(ComponentId cid) {
            m_componentId = cid;
            m_componentInfo = new ComponentInfo();
        }

        public ComponentId ComponentId {
            get {
                return m_componentId;
            }
        }

        public ComponentInfo ComponentInfo {
            get {
                return m_componentInfo;
            }
        }
    }
}

 

In Post build event:
mkdir "$(TargetDir)SubAppDomain"
copy "$(ProjectDir)AppDomain.config" "$(TargetDir)SubAppDomain"

AppDomain.Config:
< xml version="1.0" encoding="utf-8" >
<configuration></configuration>

App.Config:
< xml version="1.0" encoding="utf-8" >
<configuration></configuration>


 



.NET Development35  
 
 
tbrunk





PostPosted: Common Language Runtime, LoaderOptimization.MultiDomain incompatible with generics? Top

This is a duplicate of already closed issue.

:http://lab.msdn.microsoft.com/ProductFeedback/viewFeedback.aspx feedbackid=78623d98-6b02-43aa-b0e6-b2a1c261a9f0


 
 
nkojuharov





PostPosted: Common Language Runtime, LoaderOptimization.MultiDomain incompatible with generics? Top

The URL you've posted above doesn't seem to work anymore. Could you please post the correct URL as I have a similar issue and would like to see the resolution

Thanks