// ObjectLoader.cs
using System;
using System.Reflection;
using System.Collections;
namespace Loader{
/* contains assembly loader objects, stored in a hash
* and keyed on the .dll file they represent. Each assembly loader
* object can be referenced by the original name/path and is used to
* load objects, returned as type Object. It is up to the calling class
* to cast the object to the necessary type for consumption.
* External interfaces are highly recommended!!
* */
public class ObjectLoader : IDisposable
{
// essentially creates a parallel-hash pair setup
// one appDomain per loader
protected Hashtable domains = new Hashtable();
// one loader per assembly DLL
protected Hashtable loaders = new Hashtable();
public ObjectLoader() {/*...*/}
public object GetObject( string dllName, string typeName, object[] constructorParms )
{
Loader.AssemblyLoader al = null;
object o = null;
try{
al = (Loader.AssemblyLoader)loaders[ dllName ];
} catch (Exception){}
if( al == null )
{
AppDomainSetup setup = new AppDomainSetup();
setup.ShadowCopyFiles = "true";
AppDomain domain = AppDomain.CreateDomain( dllName, null, setup );
domains.Add( dllName, domain );
object[] parms = { dllName };
// object[] parms = null;
BindingFlags bindings = BindingFlags.CreateInstance | BindingFlags.Instance | BindingFlags.Public;
try{
al = (Loader.AssemblyLoader)domain.CreateInstanceFromAndUnwrap(
"Loader.dll", "Loader.AssemblyLoader", true, bindings, null, parms, null, null, null);
} catch (Exception){
throw new AssemblyLoadFailureException();
}
if( al != null )
{
if( !loaders.ContainsKey( dllName ) )
{
loaders.Add( dllName, al );
}
else
{
throw new AssemblyAlreadyLoadedException();
}
}
else
{
throw new AssemblyNotLoadedException();
}
}
if( al != null )
{
o = al.GetObject( typeName, constructorParms );
if( o != null && o is AssemblyNotLoadedException )
{
throw new AssemblyNotLoadedException();
}
if( o == null || o is ObjectLoadFailureException )
{
string msg = "Object could not be loaded. Check that type name " + typeName +
" and constructor parameters are correct. Ensure that type name " + typeName +
" exists in the assembly " + dllName + ".";
throw new ObjectLoadFailureException( msg );
}
}
return o;
}
public void Unload( string dllName )
{
if( domains.ContainsKey( dllName ) )
{
AppDomain domain = (AppDomain)domains[ dllName ];
AppDomain.Unload( domain );
domains.Remove( dllName );
}
}
~ObjectLoader()
{
dispose( false );
}
public void Dispose()
{
dispose( true );
}
private void dispose( bool disposing )
{
if( disposing )
{
loaders.Clear();
foreach( object o in domains.Keys )
{
string dllName = o.ToString();
Unload( dllName );
}
domains.Clear();
}
}
}
}