Search code examples
c#appdomain

How to call crossappdomaindelegate-Method with parameters


i would like to call the method crossappdomaindelegate with a method-name which needs a parameter.

Example:

myAppdomain.DoCallback(new CrossAppDomainDelegate(MyMethod));

private static void MyMethod(string myParam)
{
  Console.Write("my param="+ myParam);
}

how can I pass a parameter in new CrossAppDomainDelegate(MyMethod....)?

Update: Just to complete Maarten's answer to my specific case: I had also add an ResolveHandler to find already loaded assemblies. Just if anyone else has similar Problems.

_myNewAppDomain.AssemblyResolve += MyResolveEventHandler;

        public static Assembly MyResolveEventHandler(Object sender, ResolveEventArgs args)
        {
            var dllName = args.Name.Split(',')[0];

            var currentAppdomain = (AppDomain) sender;

            var file = currentAppdomain.GetAssemblies().FirstOrDefault(f => f.FullName.Split(',')[0] == dllName);

            return file;
        }

Solution

  • Here is one way to retrieve the types in an assembly in another AppDomain.

    First, define some dummy classes:

    public class X1 { }
    public class X2 { }
    public class X3 { }
    public class X4 { }
    public class X5 { }
    

    Then define a specific class to load the types from an assembly:

    public class TypesProvider : MarshalByRefObject
    {
        public string[] RetrieveTypes()
        {
            return Assembly.GetExecutingAssembly().GetTypes().Select(x => x.FullName).ToArray();
        }
    
        public string[] RetrieveTypesForAnotherAssembly(string assemblyFile)
        {
            return Assembly.LoadFile(assemblyFile).GetTypes().Select(x => x.FullName).ToArray();
        }
    }
    

    And use that class to retrieve the types from an assembly:

    class Program
    {
        static void Main(string[] args)
        {
            var domain = AppDomain.CreateDomain("type-provider-appdomain");
            var typeProviderInstance = domain.CreateInstanceAndUnwrap(typeof(TypesProvider).Assembly.FullName, typeof(TypesProvider).FullName) as TypesProvider;
            if (typeProviderInstance != null)
            {
                Console.WriteLine("Types for the executing assembly");
                var types = typeProviderInstance.RetrieveTypes();
                foreach (var type in types)
                {
                    Console.WriteLine(type);
                }
                var assemblyFile = new FileInfo("EntityFramework.dll").FullName;
                Console.WriteLine("Types for assembly " + assemblyFile);
                types = typeProviderInstance.RetrieveTypesForAnotherAssembly(assemblyFile);
                foreach (var type in types)
                {
                    Console.WriteLine(type);
                }
            }
            Console.ReadLine();
        }
    }
    

    The first usage of the TypesProvider will yield the dummy classes

    Types for the executing assembly
    SO_3543881.Program
    SO_3543881.TypesProvider
    SO_3543881.X1
    SO_3543881.X2
    SO_3543881.X3
    SO_3543881.X4
    SO_3543881.X5
    

    The second call will yield all types from the EntityFramework assembly (if you have placed it in the bin folder).