/// <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)); }
/// <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; }
/// <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)); }
/// <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; }