Ah... My mistake... I didn't look at your code closely enough the first
time.

The load into the helper domain succeeds. But System.Reflection.Assembly is
a MarshalByRef object, so when Load returns the reference, the helper dll
must /also/ be loaded in the current AppDomain. That's what fails.

For this to work without the need of duplicating the entire dll you need
to use a different approach to load the dll. The CreateInstanceAndUnwrap
method of AppDomain gives you an opportunity to limit the duplication
to only those classes or interfaces that need to be shared.

In order to do anything with a remote domain, you need to have access
to the metadata for the classes you intend to use. For simpler cases,
you may want to just distribute the entire dll to clients and use the
AppDomain.Load method as you are. For more complex things, you can
break things down and only share the types you want to use.

Here's an example.

I created a separate assembly (class library) called HelperInterface
containing only the following:

        public interface IHelper
        {
                int MagicNumber { get; }
        }

My AssemblyLoadHelper.dll contains the following class:

        public class Helper : MarshalByRefObject, IHelper
        {
                int magicNumber;

                public Helper()
                {
                        magicNumber = 12345;
                }

                public int MagicNumber
                {
                        get { return magicNumber; }
                }
        }

Finally, my client application, a console app, looks like this:

        class Class1
        {
                const string HELPER_BASE =
                        @"H:\Dev\VS.Net\Scratch\AssemblyLoadHelper\bin\Debug";

                [STAThread]
                static void Main(string[] args)
                {
                        Console.WriteLine( "CurrentDomain Base: {0}",
                                AppDomain.CurrentDomain.BaseDirectory );

                        AppDomainSetup setup = new AppDomainSetup();
                        setup.ApplicationBase = HELPER_BASE;
                        AppDomain helperDomain = AppDomain.CreateDomain(
                                "HelperDomain",
                                AppDomain.CurrentDomain.Evidence,
                                setup);

                        Console.WriteLine( "HelperDomain Base: {0}",
                                helperDomain.BaseDirectory );

                        AssemblyLoadHelper.IHelper helper = 
(AssemblyLoadHelper.IHelper)
                                helperDomain.CreateInstanceAndUnwrap(
                                        "AssemblyLoadHelper",
                                        "AssemblyLoadHelper.Helper",
                                        false,
                                        System.Reflection.BindingFlags.Default,
                                        null,null,null,null,null);

                        Console.WriteLine( "The Magic Number is {0}",
                                helper.MagicNumber );
                }
        }

Both the client dll and the AssemblyLoadHelper.dll have references to
HelperInterface.dll and need a copy of it in their base directories.

Since the client code doesn't use anything from AssemblyLoadHelper.dll,
it doesn't need a reference to it.

Charlie Poole
[EMAIL PROTECTED]
www.pooleconsulting.com
www.charliepoole.org



> -----Original Message-----
> From: Moderated discussion of advanced .NET topics.
> [mailto:[EMAIL PROTECTED] Behalf Of Rick Warta
> Sent: Friday, February 21, 2003 8:47 AM
> To: [EMAIL PROTECTED]
> Subject: Re: [ADVANCED-DOTNET] AppDomain.Load failure
>
>
> The assembly I'm attempting to load using AppDomain.Load only references
> System, System.Data, and System.XML, which are all FCL (v1.0.3705)
> assemblies located in the GAC.
>
> To narrow the problem down I used the C# Class Library wizard with the
> default single .cs file, in which is a single [Serializable] class
> with .ctor and a lone string property. Similarly, I created a Console
> application, in which Main creates an object that does the work. This
> worker object creates the new AppDomain, and then tries to call
> AppDomain.Load. Here's the gist of it:
>
>   // AppDomain.CurrentDomain.BaseDirectory is
>   //   "C:\AssemblyLoad\LoadApp\bin\Debug\"
>   AppDomainSetup setup = new AppDomainSetup();
>   setup.ApplicationBase = @"C:\AssemblyLoadHelper\Helper\bin\Debug\";
>   AppDomain helperDomain = AppDomain.CreateDomain("HelperDomain",
> AppDomain.CurrentDomain.Evidence, setup);
>
>   // "File or ... was not found."
>   helperAssembly = helperDomain.Load( assemblyFullName );
>
> It appears that the load machinery only supports loading assemblies from a
> sub-directory of the current app. I didn't get this from the
> docs, nor from
> Eric Gunnerson's article at:
>
> http://msdn.microsoft.com/library/default.asp?url=/library/en-
> us/dncscol/html/csharp05162002.asp
>
> thanks,
>
>   -- still perplexed...
>
>

Reply via email to