This is a thin wrapper around the .NET AppDomain class that enables safe disposal. Use these objects where you would normally grab an AppDomain object. Note that if the current application domain is passed to this class, a call to Dispose will do nothing. We will never unload the current application domain.
Inheritance: AppDomainToolkit.IDisposable
示例#1
0
        /// <summary>
        /// Creates a new Remote object.
        /// </summary>
        /// <param name="wrappedDomain">
        /// The target AppDomain, wrapped for disposable goodness.
        /// </param>
        /// <param name="constructorArgs">
        /// A list of constructor arguments to pass to the remote object.
        /// </param>
        /// <returns>
        /// A remote proxy to an object of type T living in the target wrapped application domain.
        /// </returns>
        internal static Remote <T> CreateProxy(DisposableAppDomain wrappedDomain, params object[] constructorArgs)
        {
            if (wrappedDomain == null)
            {
                throw new ArgumentNullException("domain");
            }

            var type = typeof(T);

            var proxy = (T)wrappedDomain.Domain.CreateInstanceAndUnwrap(
                type.Assembly.FullName,
                type.FullName,
                false,
                BindingFlags.CreateInstance,
                null,
                constructorArgs,
                null,
                null);

            return(new Remote <T>(wrappedDomain, proxy));
        }
示例#2
0
        /// <summary>
        /// Initializes a new instance of the AppDomainAssemblyLoader class. The assembly environment will create
        /// a new application domain with the location of the currently executing assembly as the application base. It
        /// will also add that root directory to the assembly resolver's path in order to properly load a remotable
        /// AssemblyLoader object into context. From here, add whatever assembly probe paths you wish in order to
        /// resolve remote proxies, or extend this class if you desire more specific behavior.
        /// </summary>
        /// <param name="setupInfo">
        /// The setup information.
        /// </param>
        private AppDomainContext(AppDomainSetup setupInfo)
        {
            this.UniqueId         = Guid.NewGuid();
            this.AssemblyImporter = new PathBasedAssemblyResolver();

            // Add some root directories to resolve some required assemblies
            this.AssemblyImporter.AddProbePath(setupInfo.ApplicationBase);
            this.AssemblyImporter.AddProbePath(setupInfo.PrivateBinPath);

            // Create the new domain and wrap it for disposal.
            this.wrappedDomain = new DisposableAppDomain(
                AppDomain.CreateDomain(
                    this.UniqueId.ToString(),
                    null,
                    setupInfo));

            AppDomain.CurrentDomain.AssemblyResolve += this.AssemblyImporter.Resolve;

            // Create remotes
            this.loaderProxy = Remote <AssemblyTargetLoader> .CreateProxy(this.wrappedDomain);

            this.resolverProxy = Remote <PathBasedAssemblyResolver> .CreateProxy(this.wrappedDomain);

            // Assign the resolver in the other domain (just to be safe)
            RemoteAction.Invoke(
                this.wrappedDomain.Domain,
                this.resolverProxy.RemoteObject,
                (resolver) =>
            {
                AppDomain.CurrentDomain.AssemblyResolve += resolver.Resolve;
            });

            // Assign proper paths to the remote resolver
            this.resolverProxy.RemoteObject.AddProbePath(setupInfo.ApplicationBase);
            this.resolverProxy.RemoteObject.AddProbePath(setupInfo.PrivateBinPath);

            this.IsDisposed = false;
        }
        /// <summary>
        /// Initializes a new instance of the AppDomainAssemblyLoader class. The assembly environment will create
        /// a new application domain with the location of the currently executing assembly as the application base. It
        /// will also add that root directory to the assembly resolver's path in order to properly load a remotable
        /// AssemblyLoader object into context. From here, add whatever assembly probe paths you wish in order to
        /// resolve remote proxies, or extend this class if you desire more specific behavior.
        /// </summary>
        /// <param name="setupInfo">
        /// The setup information.
        /// </param>
        private AppDomainContext(AppDomainSetup setupInfo)
        {
            this.UniqueId = Guid.NewGuid();
            this.AssemblyImporter = new PathBasedAssemblyResolver();

            // Add some root directories to resolve some required assemblies
            this.AssemblyImporter.AddProbePath(setupInfo.ApplicationBase);
            this.AssemblyImporter.AddProbePath(setupInfo.PrivateBinPath);

            // Create the new domain and wrap it for disposal.
            this.wrappedDomain = new DisposableAppDomain(
                AppDomain.CreateDomain(
                    this.UniqueId.ToString(),
                    null,
                    setupInfo));

            AppDomain.CurrentDomain.AssemblyResolve += this.AssemblyImporter.Resolve;

            // Create remotes
            this.loaderProxy = Remote<AssemblyTargetLoader>.CreateProxy(this.wrappedDomain);
            this.resolverProxy = Remote<PathBasedAssemblyResolver>.CreateProxy(this.wrappedDomain);

            // Assign the resolver in the other domain (just to be safe)
            RemoteAction.Invoke(
                this.wrappedDomain.Domain,
                this.resolverProxy.RemoteObject,
                (resolver) =>
                {
                    AppDomain.CurrentDomain.AssemblyResolve += resolver.Resolve;
                });

            // Assign proper paths to the remote resolver
            this.resolverProxy.RemoteObject.AddProbePath(setupInfo.ApplicationBase);
            this.resolverProxy.RemoteObject.AddProbePath(setupInfo.PrivateBinPath);

            this.IsDisposed = false;
        }
示例#4
0
        /// <summary>
        /// Creates a new Remote object.
        /// </summary>
        /// <param name="wrappedDomain">
        /// The target AppDomain, wrapped for disposable goodness.
        /// </param>
        /// <param name="constructorArgs">
        /// A list of constructor arguments to pass to the remote object.
        /// </param>
        /// <returns>
        /// A remote proxy to an object of type T living in the target wrapped application domain.
        /// </returns>
        internal static Remote <T> CreateProxy(DisposableAppDomain wrappedDomain, string assemblyName, string typeFullName, params object[] constructorArgs)
        {
            if (wrappedDomain == null)
            {
                throw new ArgumentNullException(nameof(wrappedDomain));
            }

            var type = typeof(T);

            var proxyHandle = Activator.CreateInstance(
                wrappedDomain.Domain,
                assemblyName ?? type.Assembly.GetName().Name,
                typeFullName ?? type.FullName,
                false,
                BindingFlags.CreateInstance,
                null,
                constructorArgs,
                null,
                null);

            var proxy = (T)proxyHandle.Unwrap();

            return(new Remote <T>(wrappedDomain, proxy));
        }
示例#5
0
 /// <summary>
 /// Initializes a new instance of the Remote class.
 /// </summary>
 /// <param name="domain">
 /// The disposable app domain where the remote object lives.
 /// </param>
 /// <param name="remoteObject">
 /// The remote object.
 /// </param>
 private Remote(DisposableAppDomain domain, T remoteObject)
 {
     this.wrappedDomain = domain;
     this.remoteObject  = remoteObject;
     this.IsDisposed    = false;
 }