2008-01-02 21:49:43 +00:00
#region = = = = = = = = = = = = = = = = = = Copyright ( c ) 2007 Pascal vd Heiden
/ *
* Copyright ( c ) 2007 Pascal vd Heiden , www . codeimp . com
* This program is released under GNU General Public License
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* /
#endregion
#region = = = = = = = = = = = = = = = = = = Namespaces
using System ;
using System.Collections ;
using System.Collections.Generic ;
using System.Globalization ;
using System.Text ;
using System.IO ;
using System.Reflection ;
2008-05-29 11:34:01 +00:00
using CodeImp.DoomBuilder.Actions ;
2008-11-27 10:33:09 +00:00
using CodeImp.DoomBuilder.Editing ;
2008-01-02 21:49:43 +00:00
#endregion
namespace CodeImp.DoomBuilder.Plugins
{
2008-05-13 22:28:30 +00:00
internal class Plugin : IDisposable
2008-01-02 21:49:43 +00:00
{
#region = = = = = = = = = = = = = = = = = = Constants
#endregion
#region = = = = = = = = = = = = = = = = = = Variables
// The plugin assembly
private Assembly asm ;
2008-05-13 22:28:30 +00:00
// The plug
private Plug plug ;
2008-01-02 21:49:43 +00:00
// Unique name used to refer to this assembly
private string name ;
// Disposing
private bool isdisposed = false ;
#endregion
#region = = = = = = = = = = = = = = = = = = Properties
public Assembly Assembly { get { return asm ; } }
2008-05-13 22:28:30 +00:00
public Plug Plug { get { return plug ; } }
2008-01-02 21:49:43 +00:00
public string Name { get { return name ; } }
public bool IsDisposed { get { return isdisposed ; } }
#endregion
#region = = = = = = = = = = = = = = = = = = Constructor / Disposer
// Constructor
public Plugin ( string filename )
{
// Initialize
2009-04-06 05:51:59 +00:00
string shortfilename = Path . GetFileName ( filename ) ;
2008-01-02 21:49:43 +00:00
name = Path . GetFileNameWithoutExtension ( filename ) ;
2009-04-06 05:51:59 +00:00
General . WriteLogLine ( "Loading plugin '" + name + "' from '" + shortfilename + "'..." ) ;
2008-05-13 22:28:30 +00:00
2009-01-10 22:34:36 +00:00
try
{
// Load assembly
asm = Assembly . LoadFile ( filename ) ;
}
catch ( Exception )
{
2009-04-06 05:51:59 +00:00
General . ErrorLogger . Add ( ErrorType . Error , "Could not load plugin \"" + shortfilename + "\", the DLL file could not be read. This file is not supposed to be in the Plugins subdirectory." ) ;
2009-01-10 22:34:36 +00:00
throw new InvalidProgramException ( ) ;
}
2008-05-13 22:28:30 +00:00
// Find the class that inherits from Plugin
Type t = FindSingleClass ( typeof ( Plug ) ) ;
if ( t ! = null )
{
// Are the multiple plug classes?
if ( FindClasses ( typeof ( Plug ) ) . Length > 1 )
{
// Show a warning
2009-04-06 05:51:59 +00:00
General . ErrorLogger . Add ( ErrorType . Warning , "Plugin \"" + shortfilename + "\" has more than one plug." ) ;
2008-05-13 22:28:30 +00:00
}
// Make plug instance
plug = CreateObject < Plug > ( t ) ;
plug . Plugin = this ;
}
else
{
// How can we plug something in without a plug?
2009-04-06 05:51:59 +00:00
General . ErrorLogger . Add ( ErrorType . Error , "Could not load plugin \"" + shortfilename + "\", plugin is missing the plug. This file is not supposed to be in the Plugins subdirectory." ) ;
2008-05-14 21:48:36 +00:00
throw new InvalidProgramException ( ) ;
2008-05-13 22:28:30 +00:00
}
2008-01-02 21:49:43 +00:00
// We have no destructor
GC . SuppressFinalize ( this ) ;
}
// Disposer
public void Dispose ( )
{
// Not already disposed?
if ( ! isdisposed )
{
// Clean up
asm = null ;
// Done
isdisposed = true ;
}
}
#endregion
#region = = = = = = = = = = = = = = = = = = Methods
2008-11-27 10:33:09 +00:00
2008-01-02 21:49:43 +00:00
// This creates a stream to read a resource or returns null when not found
2008-05-13 22:28:30 +00:00
public Stream GetResourceStream ( string resourcename )
2008-01-02 21:49:43 +00:00
{
string [ ] resnames ;
// Find a resource
resnames = asm . GetManifestResourceNames ( ) ;
foreach ( string rn in resnames )
{
// Found it?
if ( rn . EndsWith ( resourcename , StringComparison . InvariantCultureIgnoreCase ) )
{
// Get a stream from the resource
return asm . GetManifestResourceStream ( rn ) ;
}
}
// Nothing found
return null ;
}
// This finds all class types that inherits from the given type
public Type [ ] FindClasses ( Type t )
{
List < Type > found = new List < Type > ( ) ;
Type [ ] types ;
// Get all exported types
types = asm . GetExportedTypes ( ) ;
foreach ( Type it in types )
{
// Compare types
if ( t . IsAssignableFrom ( it ) ) found . Add ( it ) ;
}
// Return list
return found . ToArray ( ) ;
}
// This finds a single class type that inherits from the given type
// Returns null when no valid type was found
public Type FindSingleClass ( Type t )
{
Type [ ] types = FindClasses ( t ) ;
if ( types . Length > 0 ) return types [ 0 ] ; else return null ;
}
// This creates an instance of a class
public T CreateObject < T > ( Type t , params object [ ] args )
{
return CreateObjectA < T > ( t , args ) ;
}
// This creates an instance of a class
public T CreateObjectA < T > ( Type t , object [ ] args )
{
try
{
// Create instance
return ( T ) asm . CreateInstance ( t . FullName , false , BindingFlags . Default , null , args , CultureInfo . CurrentCulture , new object [ 0 ] ) ;
}
catch ( TargetInvocationException e )
{
// Error!
2009-03-01 09:15:58 +00:00
General . ErrorLogger . Add ( ErrorType . Error , "Failed to create class instance '" + t . Name + "' from plugin '" + name + "'" ) ;
2008-01-02 21:49:43 +00:00
General . WriteLogLine ( e . InnerException . GetType ( ) . Name + ": " + e . InnerException . Message ) ;
return default ( T ) ;
}
catch ( Exception e )
{
// Error!
2009-03-01 09:15:58 +00:00
General . ErrorLogger . Add ( ErrorType . Error , "Failed to create class instance '" + t . Name + "' from plugin '" + name + "'" ) ;
2008-01-02 21:49:43 +00:00
General . WriteLogLine ( e . GetType ( ) . Name + ": " + e . Message ) ;
return default ( T ) ;
}
}
#endregion
}
}