changeset 482:1ed2f3ab5e35

Re #419: Remove assumptions of a file-based install * Swap API to using new "loadable object" and "loadable object source" wrappers to allow file-based or memory-based loading
author IBBoard <dev@ibboard.co.uk>
date Sat, 07 Jul 2012 21:01:32 +0100
parents 81f32062c9fa
children 4d6c92744254
files API/AbstractWarFoundryLoader.cs API/Factories/AbstractNativeWarFoundryFactory.cs API/Factories/AbstractNonNativeFileExtensionWarFoundryFactory.cs API/Factories/AbstractNonNativeWarFoundryFactory.cs API/Factories/AbstractWarFoundryFactory.cs API/Factories/DummyWarFoundryFactory.cs API/Factories/IWarFoundryFactory.cs API/FileLoadFailure.cs API/Loading/ILoadableObject.cs API/Loading/ILoadableObjectSource.cs API/Loading/LoadableFileObject.cs API/Loading/LoadableObjectSourceDirectory.cs API/Loading/LoadableObjectSourceResourceSet.cs API/Loading/LoadableResourceObject.cs IBBoard.WarFoundry.API.csproj
diffstat 15 files changed, 387 insertions(+), 98 deletions(-) [+]
line diff
     1.1 --- a/API/AbstractWarFoundryLoader.cs	Mon Jun 25 21:04:02 2012 +0100
     1.2 +++ b/API/AbstractWarFoundryLoader.cs	Sat Jul 07 21:01:32 2012 +0100
     1.3 @@ -8,6 +8,7 @@
     1.4  using IBBoard.IO;
     1.5  using IBBoard.WarFoundry.API.Factories;
     1.6  using IBBoard.WarFoundry.API.Objects;
     1.7 +using IBBoard.WarFoundry.API.Loading;
     1.8  
     1.9  namespace IBBoard.WarFoundry.API
    1.10  {
    1.11 @@ -16,7 +17,7 @@
    1.12  	/// </summary>
    1.13  	public abstract class AbstractWarFoundryLoader
    1.14  	{
    1.15 -		private ICollection<DirectoryInfo> directories;
    1.16 +		private ICollection<ILoadableObjectSource> directories;
    1.17  		private ICollection<INativeWarFoundryFactory> factories;
    1.18  		private ICollection<INonNativeWarFoundryFactory> nonNativeFactories;
    1.19  		private Dictionary<IWarFoundryFactory, SimpleSet<IWarFoundryObject>> loadedObjects;
    1.20 @@ -28,8 +29,8 @@
    1.21  
    1.22  		protected AbstractWarFoundryLoader()
    1.23  		{
    1.24 -			directories = new List<DirectoryInfo>();
    1.25 -			directories.Add(new DirectoryInfo(WarFoundryLoader.DEFAULT_USER_DATA_DIR));
    1.26 +			directories = new List<ILoadableObjectSource>();
    1.27 +			directories.Add(new LoadableObjectSourceDirectory(WarFoundryLoader.DEFAULT_USER_DATA_DIR));
    1.28  			factories = new List<INativeWarFoundryFactory>();
    1.29  			nonNativeFactories = new List<INonNativeWarFoundryFactory>();
    1.30  			loadedObjects = new Dictionary<IWarFoundryFactory,SimpleSet<IWarFoundryObject>>();
    1.31 @@ -41,11 +42,23 @@
    1.32  		/// <param name="directory">
    1.33  		/// The <see cref="DirectoryInfo"/> to add to the list for searching for data files
    1.34  		/// </param>
    1.35 +		[Obsolete("Use load sources")]
    1.36  		public void AddLoadDirectory(DirectoryInfo directory)
    1.37  		{
    1.38 -			if (!directories.Contains(directory))
    1.39 +			AddLoadSource(new LoadableObjectSourceDirectory(directory));
    1.40 +		}
    1.41 +
    1.42 +		/// <summary>
    1.43 +		/// Adds a load source to the set of sources that objects will be loaded from
    1.44 +		/// </summary>
    1.45 +		/// <param name='loadSource'>
    1.46 +		/// The load source.
    1.47 +		/// </param>
    1.48 +		public void AddLoadSource(ILoadableObjectSource loadSource)
    1.49 +		{
    1.50 +			if (!directories.Contains(loadSource))
    1.51  			{
    1.52 -				directories.Add(directory);
    1.53 +				directories.Add(loadSource);
    1.54  			}
    1.55  		}
    1.56  		
    1.57 @@ -55,11 +68,17 @@
    1.58  		/// <param name="directory">
    1.59  		/// A <see cref="DirectoryInfo"/>
    1.60  		/// </param>
    1.61 +		[Obsolete("Use load sources")]
    1.62  		public void RemoveLoadDirectory(DirectoryInfo directory)
    1.63 +		{			
    1.64 +			RemoveLoadSource(new LoadableObjectSourceDirectory(directory));
    1.65 +		}
    1.66 +
    1.67 +		public void RemoveLoadSource(ILoadableObjectSource loadSource)
    1.68  		{
    1.69 -			if (directories.Contains(directory))
    1.70 +			if (directories.Contains(loadSource))
    1.71  			{
    1.72 -				directories.Remove(directory);
    1.73 +				directories.Remove(loadSource);
    1.74  			}
    1.75  		}
    1.76  		
    1.77 @@ -129,8 +148,8 @@
    1.78  		{
    1.79  			OnFileLoadingStarted();
    1.80  			PrepareForFileLoad();
    1.81 -			Dictionary<FileInfo, IWarFoundryFactory> loadableRaces = new Dictionary<FileInfo, IWarFoundryFactory>();
    1.82 -			Dictionary<FileInfo, IWarFoundryFactory> loadableGameSystems = new Dictionary<FileInfo, IWarFoundryFactory>();
    1.83 +			Dictionary<ILoadableObject, IWarFoundryFactory> loadableRaces = new Dictionary<ILoadableObject, IWarFoundryFactory>();
    1.84 +			Dictionary<ILoadableObject, IWarFoundryFactory> loadableGameSystems = new Dictionary<ILoadableObject, IWarFoundryFactory>();
    1.85  			List<FileLoadFailure> failedLoads = FillLoadableFiles(loadableRaces, loadableGameSystems);
    1.86  			failedLoads.AddRange(LoadGameSystems(loadableGameSystems));
    1.87  			failedLoads.AddRange(LoadRaces(loadableRaces));
    1.88 @@ -165,29 +184,24 @@
    1.89  			//Do nothing special
    1.90  		}
    1.91  
    1.92 -		private List<FileLoadFailure> FillLoadableFiles(Dictionary<FileInfo, IWarFoundryFactory> loadableRaces, Dictionary<FileInfo, IWarFoundryFactory> loadableGameSystems)
    1.93 +		private List<FileLoadFailure> FillLoadableFiles(Dictionary<ILoadableObject, IWarFoundryFactory> loadableRaces, Dictionary<ILoadableObject, IWarFoundryFactory> loadableGameSystems)
    1.94  		{			
    1.95  			List<FileLoadFailure> fails = new List<FileLoadFailure>();
    1.96  			
    1.97 -			foreach (DirectoryInfo directory in directories)
    1.98 +			foreach (ILoadableObjectSource directory in directories)
    1.99  			{
   1.100 -				directory.Refresh();
   1.101 -
   1.102 -				if (directory.Exists)
   1.103 -				{
   1.104 -					List<FileLoadFailure> directoryFails = FillLoadableFilesForDirectory(loadableRaces, loadableGameSystems, directory);
   1.105 -					fails.AddRange(directoryFails);
   1.106 -				}
   1.107 +				List<FileLoadFailure> directoryFails = FillLoadableFilesForDirectory(loadableRaces, loadableGameSystems, directory);
   1.108 +				fails.AddRange(directoryFails);
   1.109  			}
   1.110  			
   1.111  			return fails;
   1.112  		}
   1.113  
   1.114 -		private List<FileLoadFailure> FillLoadableFilesForDirectory(Dictionary<FileInfo, IWarFoundryFactory> loadableRaces, Dictionary<FileInfo, IWarFoundryFactory> loadableGameSystems, DirectoryInfo directory)
   1.115 +		private List<FileLoadFailure> FillLoadableFilesForDirectory(Dictionary<ILoadableObject, IWarFoundryFactory> loadableRaces, Dictionary<ILoadableObject, IWarFoundryFactory> loadableGameSystems, ILoadableObjectSource directory)
   1.116  		{
   1.117  			List<FileLoadFailure> fails = new List<FileLoadFailure>();
   1.118  		
   1.119 -			foreach (FileInfo file in directory.GetFiles())
   1.120 +			foreach (ILoadableObject file in directory.GetLoadableObjects())
   1.121  			{
   1.122  				IWarFoundryFactory factory = GetGameSystemLoadingFactoryForFile(file);
   1.123  				
   1.124 @@ -210,16 +224,11 @@
   1.125  					}
   1.126  				}
   1.127  			}
   1.128 -			
   1.129 -			foreach (DirectoryInfo subdir in directory.GetDirectories())
   1.130 -			{
   1.131 -				fails.AddRange(FillLoadableFilesForDirectory(loadableRaces, loadableGameSystems, subdir));
   1.132 -			}
   1.133  
   1.134  			return fails;
   1.135  		}
   1.136  
   1.137 -		private IWarFoundryFactory GetGameSystemLoadingFactoryForFile(FileInfo file)
   1.138 +		private IWarFoundryFactory GetGameSystemLoadingFactoryForFile(ILoadableObject file)
   1.139  		{
   1.140  			IWarFoundryFactory loadingFactory = null;
   1.141  			
   1.142 @@ -247,7 +256,7 @@
   1.143  			return loadingFactory;
   1.144  		}
   1.145  
   1.146 -		private IWarFoundryFactory GetRaceLoadingFactoryForFile(FileInfo file)
   1.147 +		private IWarFoundryFactory GetRaceLoadingFactoryForFile(ILoadableObject file)
   1.148  		{
   1.149  			IWarFoundryFactory loadingFactory = null;
   1.150  			
   1.151 @@ -275,12 +284,12 @@
   1.152  			return loadingFactory;
   1.153  		}
   1.154  
   1.155 -		private List<FileLoadFailure> LoadGameSystems(Dictionary<FileInfo, IWarFoundryFactory> gameSystemFiles)
   1.156 +		private List<FileLoadFailure> LoadGameSystems(Dictionary<ILoadableObject, IWarFoundryFactory> gameSystemFiles)
   1.157  		{
   1.158  			List<FileLoadFailure> fails = new List<FileLoadFailure>();
   1.159  
   1.160  			
   1.161 -			foreach (FileInfo file in gameSystemFiles.Keys)
   1.162 +			foreach (ILoadableObject file in gameSystemFiles.Keys)
   1.163  			{
   1.164  				FileLoadFailure failure = null;
   1.165  				
   1.166 @@ -307,11 +316,11 @@
   1.167  			return fails;
   1.168  		}
   1.169  
   1.170 -		private List<FileLoadFailure> LoadRaces(Dictionary<FileInfo, IWarFoundryFactory> raceFiles)
   1.171 +		private List<FileLoadFailure> LoadRaces(Dictionary<ILoadableObject, IWarFoundryFactory> raceFiles)
   1.172  		{
   1.173  			List<FileLoadFailure> fails = new List<FileLoadFailure>();
   1.174  			
   1.175 -			foreach (FileInfo file in raceFiles.Keys)
   1.176 +			foreach (ILoadableObject file in raceFiles.Keys)
   1.177  			{
   1.178  				FileLoadFailure failure = null;
   1.179  				
   1.180 @@ -338,7 +347,7 @@
   1.181  			return fails;
   1.182  		}
   1.183  
   1.184 -		private bool LoadObject(FileInfo file, IWarFoundryFactory factory)
   1.185 +		private bool LoadObject(ILoadableObject file, IWarFoundryFactory factory)
   1.186  		{
   1.187  			factory.RaceLoaded += StoreRace;
   1.188  			factory.GameSystemLoaded += StoreGameSystem;
   1.189 @@ -351,13 +360,18 @@
   1.190  		/// Loads a single file through the registered WarFoundryFactories, if a factory exists that supports the file format.
   1.191  		/// </summary>
   1.192  		/// <param name="file">
   1.193 -		/// A <see cref="FileInfo"/> for the file to attempt to load
   1.194 +		/// A <see cref="ILoadableObject"/> for the file to attempt to load
   1.195  		/// </param>
   1.196  		/// <returns>
   1.197  		/// An ICollection of IWarFoundryObjects loaded from <code>file</code>
   1.198  		/// </returns>
   1.199  		public ICollection<IWarFoundryObject> LoadFile(FileInfo file)
   1.200  		{
   1.201 +			return LoadObject(new LoadableFileObject(file));
   1.202 +		}
   1.203 +
   1.204 +		public ICollection<IWarFoundryObject> LoadObject(ILoadableObject file)
   1.205 +		{
   1.206  			IWarFoundryFactory loadFactory = null;
   1.207  			ICollection<IWarFoundryObject> objs = LoadFileWithNonNativeFactories(file, out loadFactory);
   1.208  				
   1.209 @@ -378,7 +392,7 @@
   1.210  			return objs;
   1.211  		}
   1.212  
   1.213 -		private ICollection<IWarFoundryObject> LoadFileWithNonNativeFactories(FileInfo file, out IWarFoundryFactory loadFactory)
   1.214 +		private ICollection<IWarFoundryObject> LoadFileWithNonNativeFactories(ILoadableObject file, out IWarFoundryFactory loadFactory)
   1.215  		{
   1.216  			ICollection<IWarFoundryObject> objs = null;
   1.217  			loadFactory = null;
   1.218 @@ -405,7 +419,7 @@
   1.219  			return objs;
   1.220  		}
   1.221  
   1.222 -		private ICollection<IWarFoundryObject> LoadFileWithNativeFactories(FileInfo file, out IWarFoundryFactory loadFactory)
   1.223 +		private ICollection<IWarFoundryObject> LoadFileWithNativeFactories(ILoadableObject file, out IWarFoundryFactory loadFactory)
   1.224  		{
   1.225  			ICollection<IWarFoundryObject> objs = null;
   1.226  			loadFactory = null;
   1.227 @@ -626,6 +640,11 @@
   1.228  
   1.229  		public Army LoadArmy(FileInfo file)
   1.230  		{
   1.231 +			return LoadArmy(new LoadableFileObject(file));
   1.232 +		}
   1.233 +
   1.234 +		public Army LoadArmy(ILoadableObject file)
   1.235 +		{
   1.236  			IWarFoundryFactory factory = GetArmyLoadingFactoryForFile(file);			
   1.237  			Army loadedArmy = null;
   1.238  			
   1.239 @@ -648,7 +667,7 @@
   1.240  			return loadedArmy;
   1.241  		}
   1.242  
   1.243 -		private IWarFoundryFactory GetArmyLoadingFactoryForFile(FileInfo file)
   1.244 +		private IWarFoundryFactory GetArmyLoadingFactoryForFile(ILoadableObject file)
   1.245  		{
   1.246  			IWarFoundryFactory loadingFactory = null;
   1.247  			
     2.1 --- a/API/Factories/AbstractNativeWarFoundryFactory.cs	Mon Jun 25 21:04:02 2012 +0100
     2.2 +++ b/API/Factories/AbstractNativeWarFoundryFactory.cs	Sat Jul 07 21:01:32 2012 +0100
     2.3 @@ -14,6 +14,7 @@
     2.4  using IBBoard.WarFoundry.API.Objects;
     2.5  using ICSharpCode.SharpZipLib.Zip;
     2.6  using IBBoard.Collections;
     2.7 +using IBBoard.WarFoundry.API.Loading;
     2.8  
     2.9  namespace IBBoard.WarFoundry.API.Factories
    2.10  {
    2.11 @@ -27,16 +28,17 @@
    2.12  			//Do nothing - just make the constructor non-public
    2.13  		}
    2.14  				
    2.15 -		protected override ZipFile GetFileAsSupportedType(FileInfo file)
    2.16 +		protected override ZipFile GetFileAsSupportedType(ILoadableObject file)
    2.17  		{
    2.18 -			ZipFile zip = null;
    2.19 -			string ext = file.Extension.ToLower();
    2.20 +			ZipFile zip = null;
    2.21 +			string name = file.Name;
    2.22 +			string ext = file.Name.Substring(name.LastIndexOf('.')).ToLower();
    2.23  
    2.24  			if (ext == ".race" || ext == ".army" || ext == ".system")
    2.25  			{
    2.26  				try
    2.27  				{
    2.28 -					zip = new ZipFile(file.FullName);
    2.29 +					zip = new ZipFile(file.GetStream());
    2.30  				}
    2.31  				catch (ZipException)
    2.32  				{
     3.1 --- a/API/Factories/AbstractNonNativeFileExtensionWarFoundryFactory.cs	Mon Jun 25 21:04:02 2012 +0100
     3.2 +++ b/API/Factories/AbstractNonNativeFileExtensionWarFoundryFactory.cs	Sat Jul 07 21:01:32 2012 +0100
     3.3 @@ -5,10 +5,11 @@
     3.4  using System.Collections.Generic;
     3.5  using System.IO;
     3.6  using IBBoard.WarFoundry.API.Objects;
     3.7 +using IBBoard.WarFoundry.API.Loading;
     3.8  
     3.9  namespace IBBoard.WarFoundry.API.Factories
    3.10  {	
    3.11 -	public abstract class AbstractNonNativeFileExtensionWarFoundryFactory : AbstractNonNativeWarFoundryFactory<FileInfo>
    3.12 +	public abstract class AbstractNonNativeFileExtensionWarFoundryFactory : AbstractNonNativeWarFoundryFactory<ILoadableObject>
    3.13  	{
    3.14  		protected abstract string ArmyFileExtension { get; }
    3.15  
    3.16 @@ -16,38 +17,38 @@
    3.17  
    3.18  		protected abstract string GameSystemFileExtension { get; }
    3.19  		
    3.20 -		protected override bool CheckCanHandleFileFormat(FileInfo file)
    3.21 +		protected override bool CheckCanHandleFileFormat(ILoadableObject file)
    3.22  		{
    3.23  			return CheckCanHandleFileAsArmy(file) || CheckCanHandleFileAsRace(file) || CheckCanHandleFileAsGameSystem(file);
    3.24  		}
    3.25  		
    3.26 -		protected override bool CheckCanHandleFileAsArmy(FileInfo file)
    3.27 +		protected override bool CheckCanHandleFileAsArmy(ILoadableObject file)
    3.28  		{
    3.29  			return ArmyFileExtension != null && file.Name.ToLower().EndsWith(ArmyFileExtension);
    3.30  		}
    3.31  		
    3.32 -		protected override bool CheckCanHandleFileAsRace(FileInfo file)
    3.33 +		protected override bool CheckCanHandleFileAsRace(ILoadableObject file)
    3.34  		{
    3.35  			return RaceFileExtension != null && file.Name.ToLower().EndsWith(RaceFileExtension);
    3.36  		}
    3.37  		
    3.38 -		protected override bool CheckCanHandleFileAsGameSystem(FileInfo file)
    3.39 +		protected override bool CheckCanHandleFileAsGameSystem(ILoadableObject file)
    3.40  		{
    3.41  			return GameSystemFileExtension != null && file.Name.ToLower().EndsWith(GameSystemFileExtension);
    3.42  		}
    3.43  		
    3.44 -		protected override FileInfo GetFileAsSupportedType(FileInfo file)
    3.45 +		protected override ILoadableObject GetFileAsSupportedType(ILoadableObject file)
    3.46  		{
    3.47  			return file;
    3.48  		}
    3.49  		
    3.50 -		protected abstract Army CreateArmyFromFile(FileInfo file);
    3.51 +		protected abstract Army CreateArmyFromFile(ILoadableObject file);
    3.52  
    3.53 -		protected abstract Race CreateRaceFromFile(FileInfo file);
    3.54 +		protected abstract Race CreateRaceFromFile(ILoadableObject file);
    3.55  
    3.56 -		protected abstract GameSystem CreateGameSystemFromFile(FileInfo file);
    3.57 +		protected abstract GameSystem CreateGameSystemFromFile(ILoadableObject file);
    3.58  		
    3.59 -		protected override ICollection<IWarFoundryObject> DoCreateObjectsFromFile(FileInfo file)
    3.60 +		protected override ICollection<IWarFoundryObject> DoCreateObjectsFromFile(ILoadableObject file)
    3.61  		{
    3.62  			IWarFoundryObject obj = null;
    3.63  			
     4.1 --- a/API/Factories/AbstractNonNativeWarFoundryFactory.cs	Mon Jun 25 21:04:02 2012 +0100
     4.2 +++ b/API/Factories/AbstractNonNativeWarFoundryFactory.cs	Sat Jul 07 21:01:32 2012 +0100
     4.3 @@ -10,6 +10,6 @@
     4.4  {
     4.5  	public abstract class AbstractNonNativeWarFoundryFactory<FILE_TYPE> : AbstractWarFoundryFactory<FILE_TYPE>, INonNativeWarFoundryFactory
     4.6  	{
     4.7 -		public abstract string NonNativeDataType { get;	}
     4.8 +		public abstract string NonNativeDataType { get; }
     4.9  	}
    4.10  }
     5.1 --- a/API/Factories/AbstractWarFoundryFactory.cs	Mon Jun 25 21:04:02 2012 +0100
     5.2 +++ b/API/Factories/AbstractWarFoundryFactory.cs	Sat Jul 07 21:01:32 2012 +0100
     5.3 @@ -6,6 +6,7 @@
     5.4  using System.IO;
     5.5  using System.Collections.Generic;
     5.6  using IBBoard.WarFoundry.API.Objects;
     5.7 +using IBBoard.WarFoundry.API.Loading;
     5.8  
     5.9  namespace IBBoard.WarFoundry.API.Factories
    5.10  {
    5.11 @@ -23,7 +24,7 @@
    5.12  			obj.SetAsFullyLoaded();
    5.13  		}
    5.14  
    5.15 -		public bool CanHandleFileFormat (FileInfo file)
    5.16 +		public bool CanHandleFileFormat(ILoadableObject file)
    5.17  		{
    5.18  			FILE_TYPE typedFile = GetFileAsSupportedType(file);
    5.19  			bool canHandle = typedFile != null && CheckCanHandleFileFormat(typedFile);
    5.20 @@ -36,7 +37,7 @@
    5.21  			return canHandle;
    5.22  		}
    5.23  
    5.24 -		public bool CanHandleFileAsRace(FileInfo file)
    5.25 +		public bool CanHandleFileAsRace(ILoadableObject file)
    5.26  		{
    5.27  			FILE_TYPE typedFile = GetFileAsSupportedType(file);
    5.28  			bool canHandle = typedFile != null && CheckCanHandleFileAsRace(typedFile);
    5.29 @@ -49,7 +50,7 @@
    5.30  			return canHandle;
    5.31  		}
    5.32  
    5.33 -		public bool CanHandleFileAsGameSystem(FileInfo file)
    5.34 +		public bool CanHandleFileAsGameSystem(ILoadableObject file)
    5.35  		{
    5.36  			FILE_TYPE typedFile = GetFileAsSupportedType(file);
    5.37  			bool canHandle = typedFile != null && CheckCanHandleFileAsGameSystem(typedFile);
    5.38 @@ -62,7 +63,7 @@
    5.39  			return canHandle;
    5.40  		}
    5.41  
    5.42 -		public bool CanHandleFileAsArmy(FileInfo file)
    5.43 +		public bool CanHandleFileAsArmy(ILoadableObject file)
    5.44  		{
    5.45  			FILE_TYPE typedFile = GetFileAsSupportedType(file);
    5.46  			bool canHandle = typedFile != null && CheckCanHandleFileAsArmy(typedFile);
    5.47 @@ -81,16 +82,16 @@
    5.48  		}
    5.49  		
    5.50  		/// <summary>
    5.51 -		/// Converts the <see cref="FileInfo"/> object in to the appropriate type for this class so that it can perform its checks. If no conversion is required (the test can be performed on a <see cref="FileInfo"/> object) the object should be returned with no modification. 
    5.52 +		/// Converts the <see cref="ILoadableObject"/> object in to the appropriate type for this class so that it can perform its checks. If no conversion is required (the test can be performed on a <see cref="ILoadableObject"/> object) the object should be returned with no modification. 
    5.53  		/// If the file is not of supported type the <code>null</code> should be returned.
    5.54  		/// </summary>
    5.55  		/// <param name="file">
    5.56 -		/// A <see cref="FileInfo"/> to get the supported source object from.
    5.57 +		/// A <see cref="ILoadableObject"/> to get the supported source object from.
    5.58  		/// </param>
    5.59  		/// <returns>
    5.60 -		/// An object of type <see cref="FILE_TYPE"/> that has been converted from the input <see cref="FileInfo"/> object, or <code>null</code> if the conversion cannot be made.
    5.61 +		/// An object of type <see cref="FILE_TYPE"/> that has been converted from the input <see cref="ILoadableObject"/> object, or <code>null</code> if the conversion cannot be made.
    5.62  		/// </returns>
    5.63 -		protected abstract FILE_TYPE GetFileAsSupportedType(FileInfo file);
    5.64 +		protected abstract FILE_TYPE GetFileAsSupportedType(ILoadableObject file);
    5.65  		
    5.66  		/// <summary>
    5.67  		/// Checks whether the factory thinks it can load data from the file in its paramaterised type.
    5.68 @@ -137,7 +138,7 @@
    5.69  		protected abstract bool CheckCanHandleFileAsArmy(FILE_TYPE file);
    5.70  		
    5.71  		
    5.72 -		public ICollection<IWarFoundryObject> CreateObjectsFromFile(FileInfo file)
    5.73 +		public ICollection<IWarFoundryObject> CreateObjectsFromFile(ILoadableObject file)
    5.74  		{
    5.75  			return DoCreateObjectsFromFile(GetFileAsSupportedType(file));
    5.76  		}
     6.1 --- a/API/Factories/DummyWarFoundryFactory.cs	Mon Jun 25 21:04:02 2012 +0100
     6.2 +++ b/API/Factories/DummyWarFoundryFactory.cs	Sat Jul 07 21:01:32 2012 +0100
     6.3 @@ -6,6 +6,7 @@
     6.4  using IBBoard.WarFoundry.API.Objects;
     6.5  using System.IO;
     6.6  using System.Collections.Generic;
     6.7 +using IBBoard.WarFoundry.API.Loading;
     6.8  
     6.9  namespace IBBoard.WarFoundry.API.Factories
    6.10  {
    6.11 @@ -33,27 +34,27 @@
    6.12  			obj.SetAsFullyLoaded();
    6.13  		}
    6.14  
    6.15 -		public bool CanHandleFileFormat(FileInfo file)
    6.16 +		public bool CanHandleFileFormat(ILoadableObject file)
    6.17  		{
    6.18  			return false;
    6.19  		}
    6.20  
    6.21 -		public bool CanHandleFileAsRace(FileInfo file)
    6.22 +		public bool CanHandleFileAsRace(ILoadableObject file)
    6.23  		{
    6.24  			return false;
    6.25  		}
    6.26  
    6.27 -		public bool CanHandleFileAsGameSystem(FileInfo file)
    6.28 +		public bool CanHandleFileAsGameSystem(ILoadableObject file)
    6.29  		{
    6.30  			return false;
    6.31  		}
    6.32  
    6.33 -		public bool CanHandleFileAsArmy(FileInfo file)
    6.34 +		public bool CanHandleFileAsArmy(ILoadableObject file)
    6.35  		{
    6.36  			return false;
    6.37  		}
    6.38  
    6.39 -		public ICollection<IWarFoundryObject> CreateObjectsFromFile(FileInfo file)
    6.40 +		public ICollection<IWarFoundryObject> CreateObjectsFromFile(ILoadableObject file)
    6.41  		{
    6.42  			return new List<IWarFoundryObject>();
    6.43  		}
     7.1 --- a/API/Factories/IWarFoundryFactory.cs	Mon Jun 25 21:04:02 2012 +0100
     7.2 +++ b/API/Factories/IWarFoundryFactory.cs	Sat Jul 07 21:01:32 2012 +0100
     7.3 @@ -6,6 +6,7 @@
     7.4  using System.IO;
     7.5  using System.Collections.Generic;
     7.6  using IBBoard.WarFoundry.API.Objects;
     7.7 +using IBBoard.WarFoundry.API.Loading;
     7.8  
     7.9  namespace IBBoard.WarFoundry.API.Factories
    7.10  {
    7.11 @@ -29,45 +30,45 @@
    7.12  		/// Checks if the factory thinks it can handle the supplied file. Checks can be performed on file extension or some basic check of file content, or some other method.
    7.13  		/// </summary>
    7.14  		/// <param name="file">
    7.15 -		/// A <see cref="FileInfo"/> for the file to check support for.
    7.16 +		/// A <see cref="ILoadableObject"/> for the file to check support for.
    7.17  		/// </param>
    7.18  		/// <returns>
    7.19  		/// <code>true</code> if the file appears to be supported for loading by this factory, else returns <code>false</code>
    7.20  		/// </returns>
    7.21 -		bool CanHandleFileFormat(FileInfo file);
    7.22 +		bool CanHandleFileFormat(ILoadableObject file);
    7.23  
    7.24  		/// <summary>
    7.25  		/// Checks if the factory thinks it can handle the supplied file as a Race. Checks can be performed on file extension or some basic check of file content, or some other method.
    7.26  		/// </summary>
    7.27  		/// <param name="file">
    7.28 -		/// A <see cref="FileInfo"/> for the file to check support for as a file containing Race information.
    7.29 +		/// A <see cref="ILoadableObject"/> for the file to check support for as a file containing Race information.
    7.30  		/// </param>
    7.31  		/// <returns>
    7.32  		/// <code>true</code> if the file appears to be supported for loading by this factory as a Race, else returns <code>false</code>
    7.33  		/// </returns>
    7.34 -		bool CanHandleFileAsRace(FileInfo file);
    7.35 +		bool CanHandleFileAsRace(ILoadableObject file);
    7.36  
    7.37  		/// <summary>
    7.38  		/// Checks if the factory thinks it can handle the supplied file as a GameSystem. Checks can be performed on file extension or some basic check of file content, or some other method.
    7.39  		/// </summary>
    7.40  		/// <param name="file">
    7.41 -		/// A <see cref="FileInfo"/> for the file to check support for as a file containing GameSystem information.
    7.42 +		/// A <see cref="ILoadableObject"/> for the file to check support for as a file containing GameSystem information.
    7.43  		/// </param>
    7.44  		/// <returns>
    7.45  		/// <code>true</code> if the file appears to be supported for loading by this factory as a GameSystem, else returns <code>false</code>
    7.46  		/// </returns>
    7.47 -		bool CanHandleFileAsGameSystem(FileInfo file);
    7.48 +		bool CanHandleFileAsGameSystem(ILoadableObject file);
    7.49  
    7.50  		/// <summary>
    7.51  		/// Checks if the factory thinks it can handle the supplied file as a Army. Checks can be performed on file extension or some basic check of file content, or some other method.
    7.52  		/// </summary>
    7.53  		/// <param name="file">
    7.54 -		/// A <see cref="FileInfo"/> for the file to check support for as a file containing Army information.
    7.55 +		/// A <see cref="ILoadableObject"/> for the file to check support for as a file containing Army information.
    7.56  		/// </param>
    7.57  		/// <returns>
    7.58  		/// <code>true</code> if the file appears to be supported for loading by this factory as a Army, else returns <code>false</code>
    7.59  		/// </returns>
    7.60 -		bool CanHandleFileAsArmy(FileInfo file);
    7.61 +		bool CanHandleFileAsArmy(ILoadableObject file);
    7.62  		
    7.63  		/// <summary>
    7.64  		/// Reads the data from the supplied file and returns it as a collection of loadable objects. In addition, it fires the appropriate XxxLoaded event
    7.65 @@ -76,11 +77,11 @@
    7.66  		/// May throw a <see cref=" IBBoard.IO.InvalidFileException"/> if the file is supported by the Factory but the content is invalid.
    7.67  		/// </summary>
    7.68  		/// <param name="file">
    7.69 -		/// A <see cref="FileInfo"/> for the file to load data from
    7.70 +		/// A <see cref="ILoadableObject"/> for the file to load data from
    7.71  		/// </param>
    7.72  		/// <returns>
    7.73  		/// A <see cref="ICollection`1"/> of <see cref="IWarFoundryObject"/>s that were loaded from the file
    7.74  		/// </returns>
    7.75 -		ICollection<IWarFoundryObject> CreateObjectsFromFile(FileInfo file);
    7.76 +		ICollection<IWarFoundryObject> CreateObjectsFromFile(ILoadableObject file);
    7.77  	}
    7.78  }
     8.1 --- a/API/FileLoadFailure.cs	Mon Jun 25 21:04:02 2012 +0100
     8.2 +++ b/API/FileLoadFailure.cs	Sat Jul 07 21:01:32 2012 +0100
     8.3 @@ -6,6 +6,7 @@
     8.4  using System.IO;
     8.5  using IBBoard.Lang;
     8.6  using IBBoard.WarFoundry.API.Factories;
     8.7 +using IBBoard.WarFoundry.API.Loading;
     8.8  
     8.9  namespace IBBoard.WarFoundry.API
    8.10  {
    8.11 @@ -14,7 +15,7 @@
    8.12  	/// </summary>
    8.13  	public class FileLoadFailure
    8.14  	{
    8.15 -		private FileInfo failedFile;
    8.16 +		private ILoadableObject failedFile;
    8.17  		private IWarFoundryFactory loadingFactory;
    8.18  		private string defaultMessage;
    8.19  		private string messageTranslationID;
    8.20 @@ -25,7 +26,7 @@
    8.21  		/// Constructor for a failed file load where no factory was found. Translatable messages can be providied through a <code>translationID</code> or skipped by passing <code>null</code>.
    8.22  		/// </summary>
    8.23  		/// <param name="file">
    8.24 -		/// The <see cref="FileInfo"/> that failed to load
    8.25 +		/// The <see cref="ILoadableObject"/> that failed to load
    8.26  		/// </param>
    8.27  		/// <param name="message">
    8.28  		/// A message about the failure in English - used as a default fall-back message.
    8.29 @@ -33,7 +34,7 @@
    8.30  		/// <param name="translationID">
    8.31  		/// The ID of a translation for the message.
    8.32  		/// </param>
    8.33 -		public FileLoadFailure(FileInfo file, string message, string translationID) : this (file, null, message, "")
    8.34 +		public FileLoadFailure(ILoadableObject file, string message, string translationID) : this (file, null, message, "")
    8.35  		{
    8.36  		}
    8.37  		
    8.38 @@ -41,7 +42,7 @@
    8.39  		/// Constructor for a failed file load where a factory was identified as supporting the file but failed to load it. Translatable messages can be providied through a <code>translationID</code> or skipped by passing <code>null</code>.
    8.40  		/// </summary>
    8.41  		/// <param name="file">
    8.42 -		/// The <see cref="FileInfo"/> that failed to load
    8.43 +		/// The <see cref="ILoadableObject"/> that failed to load
    8.44  		/// </param>
    8.45  		/// <param name="factory">
    8.46  		/// The <see cref="IWarFoundryFactory"/> that failed to load the file
    8.47 @@ -52,7 +53,7 @@
    8.48  		/// <param name="translationID">
    8.49  		/// The ID of a translation for the message.
    8.50  		/// </param>
    8.51 -		public FileLoadFailure(FileInfo file, IWarFoundryFactory factory, string message, string translationID) : this(file, factory, message, translationID, null)
    8.52 +		public FileLoadFailure(ILoadableObject file, IWarFoundryFactory factory, string message, string translationID) : this(file, factory, message, translationID, null)
    8.53  		{
    8.54  		}
    8.55  		
    8.56 @@ -60,7 +61,7 @@
    8.57  		/// Constructor for a failed file load where a factory was identified as supporting the file but an exception occurred while loading it. Translatable messages can be providied through a <code>translationID</code> or skipped by passing <code>null</code>.
    8.58  		/// </summary>
    8.59  		/// <param name="file">
    8.60 -		/// The <see cref="FileInfo"/> that failed to load
    8.61 +		/// The <see cref="ILoadableObject"/> that failed to load
    8.62  		/// </param>
    8.63  		/// <param name="factory">
    8.64  		/// The <see cref="IWarFoundryFactory"/> that failed to load the file
    8.65 @@ -74,7 +75,7 @@
    8.66  		/// <param name="exception">
    8.67  		/// The <see cref="Exception"/> that occurred to cause the load to fail
    8.68  		/// </param>
    8.69 -		public FileLoadFailure(FileInfo file, IWarFoundryFactory factory, string message, string translationID, Exception exception)
    8.70 +		public FileLoadFailure(ILoadableObject file, IWarFoundryFactory factory, string message, string translationID, Exception exception)
    8.71  		{
    8.72  			failedFile = file;
    8.73  			loadingFactory = factory;
    8.74 @@ -83,7 +84,7 @@
    8.75  			cause = exception;
    8.76  		}
    8.77  
    8.78 -		public FileInfo FailedFile
    8.79 +		public ILoadableObject FailedFile
    8.80  		{
    8.81  			get
    8.82  			{
    8.83 @@ -97,14 +98,14 @@
    8.84  			{
    8.85  				if (message == null)
    8.86  				{
    8.87 -					string fileName = FailedFile.FullName;
    8.88 +					string fileName = FailedFile.Name;
    8.89  					string factoryType = (loadingFactory == null ? "" : loadingFactory.GetType().Name);
    8.90  					if (String.IsNullOrEmpty(messageTranslationID))
    8.91  					{
    8.92  						message = String.Format(defaultMessage, fileName, factoryType);
    8.93 -				 	}
    8.94 +					}
    8.95  					else
    8.96 -				 	{
    8.97 +					{
    8.98  						message = Translation.GetTranslation(messageTranslationID, defaultMessage, fileName, factoryType);
    8.99  					}
   8.100  				}
     9.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     9.2 +++ b/API/Loading/ILoadableObject.cs	Sat Jul 07 21:01:32 2012 +0100
     9.3 @@ -0,0 +1,27 @@
     9.4 +// This file (ILoadableObject.cs) is a part of the IBBoard.WarFoundry.API project and is copyright 2012 IBBoard
     9.5 +//
     9.6 +// The file and the library/program it is in are licensed and distributed, without warranty, under the GNU Affero GPL license, either version 3 of the License or (at your option) any later version. Please see COPYING for more information and the full license.
     9.7 +using System;
     9.8 +using System.IO;
     9.9 +
    9.10 +namespace IBBoard.WarFoundry.API.Loading
    9.11 +{
    9.12 +	/// <summary>
    9.13 +	/// Interface for objects that are the source of WarFoundryObjects that can be loaded by a Factory.
    9.14 +	/// Examples include files and streams.
    9.15 +	/// </summary>
    9.16 +	public interface ILoadableObject
    9.17 +	{
    9.18 +		string Name { get; }
    9.19 +
    9.20 +		/// <summary>
    9.21 +		/// Gets the stream for the loadable object that the WarFoundryObject can be loaded from. This stream will be
    9.22 +		/// created each time the method is called and must be disposed of by the calling function.
    9.23 +		/// </summary>
    9.24 +		/// <returns>
    9.25 +		/// The stream for the source.
    9.26 +		/// </returns>
    9.27 +		Stream GetStream();
    9.28 +	}
    9.29 +}
    9.30 +
    10.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    10.2 +++ b/API/Loading/ILoadableObjectSource.cs	Sat Jul 07 21:01:32 2012 +0100
    10.3 @@ -0,0 +1,21 @@
    10.4 +// This file (ILoadableObjectSource.cs) is a part of the IBBoard.WarFoundry.API project and is copyright 2012 IBBoard
    10.5 +//
    10.6 +// The file and the library/program it is in are licensed and distributed, without warranty, under the GNU Affero GPL license, either version 3 of the License or (at your option) any later version. Please see COPYING for more information and the full license.
    10.7 +using System;
    10.8 +using System.Collections.Generic;
    10.9 +
   10.10 +
   10.11 +namespace IBBoard.WarFoundry.API.Loading
   10.12 +{
   10.13 +	public interface ILoadableObjectSource
   10.14 +	{
   10.15 +		/// <summary>
   10.16 +		/// Gets the loadable objects that this source can provide
   10.17 +		/// </summary>
   10.18 +		/// <returns>
   10.19 +		/// The loadable objects.
   10.20 +		/// </returns>
   10.21 +		ICollection<ILoadableObject> GetLoadableObjects();
   10.22 +	}
   10.23 +}
   10.24 +
    11.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    11.2 +++ b/API/Loading/LoadableFileObject.cs	Sat Jul 07 21:01:32 2012 +0100
    11.3 @@ -0,0 +1,37 @@
    11.4 +// This file (LoadableFileObject.cs) is a part of the IBBoard.WarFoundry.API project and is copyright 2012 IBBoard
    11.5 +//
    11.6 +// The file and the library/program it is in are licensed and distributed, without warranty, under the GNU Affero GPL license, either version 3 of the License or (at your option) any later version. Please see COPYING for more information and the full license.
    11.7 +using System;
    11.8 +using System.IO;
    11.9 +
   11.10 +namespace IBBoard.WarFoundry.API.Loading
   11.11 +{
   11.12 +	public class LoadableFileObject : ILoadableObject
   11.13 +	{
   11.14 +		private FileInfo file;
   11.15 +
   11.16 +		public LoadableFileObject(string filePath) : this(new FileInfo(filePath))
   11.17 +		{
   11.18 +			//Do nothing extra
   11.19 +		}
   11.20 +
   11.21 +		public LoadableFileObject(FileInfo file)
   11.22 +		{
   11.23 +			this.file = file;
   11.24 +		}
   11.25 +
   11.26 +		public string Name
   11.27 +		{
   11.28 +			get
   11.29 +			{
   11.30 +				return file.FullName;
   11.31 +			}
   11.32 +		}
   11.33 +
   11.34 +		public Stream GetStream()
   11.35 +		{
   11.36 +			return new FileStream(file.FullName, FileMode.Open);
   11.37 +		}
   11.38 +	}
   11.39 +}
   11.40 +
    12.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    12.2 +++ b/API/Loading/LoadableObjectSourceDirectory.cs	Sat Jul 07 21:01:32 2012 +0100
    12.3 @@ -0,0 +1,75 @@
    12.4 +// This file (LoadableObjectSourceDirectory.cs) is a part of the IBBoard.WarFoundry.API project and is copyright 2012 IBBoard
    12.5 +//
    12.6 +// The file and the library/program it is in are licensed and distributed, without warranty, under the GNU Affero GPL license, either version 3 of the License or (at your option) any later version. Please see COPYING for more information and the full license.
    12.7 +using System;
    12.8 +using System.IO;
    12.9 +using System.Collections.Generic;
   12.10 +
   12.11 +namespace IBBoard.WarFoundry.API.Loading
   12.12 +{
   12.13 +	public class LoadableObjectSourceDirectory : ILoadableObjectSource
   12.14 +	{
   12.15 +		private DirectoryInfo dir;
   12.16 +
   12.17 +		public LoadableObjectSourceDirectory(string directory) : this(new DirectoryInfo(directory))
   12.18 +		{
   12.19 +			//Do nothing extra
   12.20 +		}
   12.21 +
   12.22 +		public LoadableObjectSourceDirectory(DirectoryInfo directory)
   12.23 +		{
   12.24 +			dir = directory;
   12.25 +		}
   12.26 +
   12.27 +		public ICollection<ILoadableObject> GetLoadableObjects()
   12.28 +		{
   12.29 +			ICollection<ILoadableObject> loadables;
   12.30 +			dir.Refresh();
   12.31 +
   12.32 +			if (dir.Exists)
   12.33 +			{
   12.34 +				loadables = GetLoadableObjectsFromDirectory(dir);
   12.35 +			}
   12.36 +			else
   12.37 +			{
   12.38 +				loadables = new List<ILoadableObject>();
   12.39 +			}
   12.40 +
   12.41 +			return loadables;
   12.42 +		}
   12.43 +
   12.44 +		private ICollection<ILoadableObject> GetLoadableObjectsFromDirectory(DirectoryInfo directory)
   12.45 +		{
   12.46 +			List<ILoadableObject> loadables = new List<ILoadableObject>();
   12.47 +
   12.48 +			foreach (FileInfo file in directory.GetFiles())
   12.49 +			{
   12.50 +				loadables.Add(new LoadableFileObject(file));
   12.51 +			}
   12.52 +
   12.53 +			foreach (DirectoryInfo subdir in directory.GetDirectories())
   12.54 +			{
   12.55 +				loadables.AddRange(GetLoadableObjectsFromDirectory(subdir));
   12.56 +			}
   12.57 +
   12.58 +			return loadables;
   12.59 +		}
   12.60 +
   12.61 +		public override bool Equals(object obj)
   12.62 +		{			
   12.63 +			if (obj == null || !obj.GetType().Equals(GetType()))
   12.64 +			{
   12.65 +				return false;
   12.66 +			}
   12.67 +
   12.68 +			LoadableObjectSourceDirectory other = (LoadableObjectSourceDirectory)obj;
   12.69 +			return this.dir.FullName.Equals(other.dir.FullName);
   12.70 +		}
   12.71 +
   12.72 +		public override int GetHashCode()
   12.73 +		{
   12.74 +			return dir.FullName.GetHashCode() + 17;
   12.75 +		}
   12.76 +	}
   12.77 +}
   12.78 +
    13.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    13.2 +++ b/API/Loading/LoadableObjectSourceResourceSet.cs	Sat Jul 07 21:01:32 2012 +0100
    13.3 @@ -0,0 +1,61 @@
    13.4 +// This file (LoadableObjectSourceResourceSet.cs) is a part of the IBBoard.WarFoundry.API project and is copyright 2012 IBBoard
    13.5 +//
    13.6 +// The file and the library/program it is in are licensed and distributed, without warranty, under the GNU Affero GPL license, either version 3 of the License or (at your option) any later version. Please see COPYING for more information and the full license.
    13.7 +using System;
    13.8 +using System.Reflection;
    13.9 +using System.Collections.Generic;
   13.10 +
   13.11 +namespace IBBoard.WarFoundry.API.Loading
   13.12 +{
   13.13 +	public class LoadableObjectSourceResourceSet : ILoadableObjectSource
   13.14 +	{
   13.15 +		private ICollection<ILoadableObject> loadables;
   13.16 +		private Assembly assm;
   13.17 +		private string[] resIDs;
   13.18 +
   13.19 +		public LoadableObjectSourceResourceSet(Assembly assembly, params string[] resourceIDs)
   13.20 +		{
   13.21 +			assm = assembly;
   13.22 +			resIDs = resourceIDs;
   13.23 +		}
   13.24 +
   13.25 +		public ICollection<ILoadableObject> GetLoadableObjects()
   13.26 +		{
   13.27 +			if (loadables == null)
   13.28 +			{
   13.29 +				loadables = new List<ILoadableObject>();
   13.30 +
   13.31 +				foreach (string resourceID in resIDs)
   13.32 +				{
   13.33 +					loadables.Add(new LoadableResourceObject(assm, resourceID));
   13.34 +				}
   13.35 +			}
   13.36 +
   13.37 +			return loadables;
   13.38 +		}
   13.39 +
   13.40 +		public override bool Equals(object obj)
   13.41 +		{
   13.42 +			if (obj == null || !obj.GetType().Equals(GetType()))
   13.43 +			{
   13.44 +				return false;
   13.45 +			}
   13.46 +
   13.47 +			LoadableObjectSourceResourceSet other = (LoadableObjectSourceResourceSet)obj;
   13.48 +			return this.assm == other.assm && Arrays.Difference(this.resIDs, other.resIDs).Length == 0;
   13.49 +		}
   13.50 +
   13.51 +		public override int GetHashCode()
   13.52 +		{
   13.53 +			int hash = assm.GetHashCode();
   13.54 +
   13.55 +			foreach (string resID in resIDs)
   13.56 +			{
   13.57 +				hash += resID.GetHashCode();
   13.58 +			}
   13.59 +
   13.60 +			return hash;
   13.61 +		}
   13.62 +	}
   13.63 +}
   13.64 +
    14.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    14.2 +++ b/API/Loading/LoadableResourceObject.cs	Sat Jul 07 21:01:32 2012 +0100
    14.3 @@ -0,0 +1,35 @@
    14.4 +// This file (LoadableResourceObject.cs) is a part of the IBBoard.WarFoundry.API project and is copyright 2012 IBBoard
    14.5 +//
    14.6 +// The file and the library/program it is in are licensed and distributed, without warranty, under the GNU Affero GPL license, either version 3 of the License or (at your option) any later version. Please see COPYING for more information and the full license.
    14.7 +using System;
    14.8 +using System.Reflection;
    14.9 +using System.IO;
   14.10 +
   14.11 +namespace IBBoard.WarFoundry.API.Loading
   14.12 +{
   14.13 +	public class LoadableResourceObject : ILoadableObject
   14.14 +	{
   14.15 +		private Assembly assm;
   14.16 +		private string resID;
   14.17 +
   14.18 +		public LoadableResourceObject(Assembly srcAssembly, string resourceID)
   14.19 +		{
   14.20 +			assm = srcAssembly;
   14.21 +			resID = resourceID;
   14.22 +		}
   14.23 +		
   14.24 +		public string Name
   14.25 +		{
   14.26 +			get
   14.27 +			{
   14.28 +				return String.Format("{0}: {1}", assm.FullName, resID);
   14.29 +			}
   14.30 +		}
   14.31 +		
   14.32 +		public Stream GetStream()
   14.33 +		{
   14.34 +			return assm.GetManifestResourceStream(resID);
   14.35 +		}
   14.36 +	}
   14.37 +}
   14.38 +
    15.1 --- a/IBBoard.WarFoundry.API.csproj	Mon Jun 25 21:04:02 2012 +0100
    15.2 +++ b/IBBoard.WarFoundry.API.csproj	Sat Jul 07 21:01:32 2012 +0100
    15.3 @@ -33,9 +33,9 @@
    15.4      <BootstrapperEnabled>true</BootstrapperEnabled>
    15.5    </PropertyGroup>
    15.6    <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
    15.7 -    <DebugSymbols>true</DebugSymbols>
    15.8 +    <DebugSymbols>True</DebugSymbols>
    15.9      <DebugType>full</DebugType>
   15.10 -    <Optimize>false</Optimize>
   15.11 +    <Optimize>False</Optimize>
   15.12      <OutputPath>bin\Debug\</OutputPath>
   15.13      <DefineConstants>DEBUG;TRACE</DefineConstants>
   15.14      <ErrorReport>prompt</ErrorReport>
   15.15 @@ -43,7 +43,7 @@
   15.16    </PropertyGroup>
   15.17    <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
   15.18      <DebugType>pdbonly</DebugType>
   15.19 -    <Optimize>true</Optimize>
   15.20 +    <Optimize>True</Optimize>
   15.21      <OutputPath>bin\Release\</OutputPath>
   15.22      <DefineConstants>TRACE</DefineConstants>
   15.23      <ErrorReport>prompt</ErrorReport>
   15.24 @@ -162,6 +162,12 @@
   15.25      <Compile Include="API\Objects\Requirement\RaceRequiresNoMoreThanNUnitsRequirement.cs" />
   15.26      <Compile Include="API\Objects\Requirement\Context\AddingContext.cs" />
   15.27      <Compile Include="API\Objects\Requirement\Context\AddingToParentContext.cs" />
   15.28 +    <Compile Include="API\Loading\ILoadableObject.cs" />
   15.29 +    <Compile Include="API\Loading\LoadableFileObject.cs" />
   15.30 +    <Compile Include="API\Loading\LoadableResourceObject.cs" />
   15.31 +    <Compile Include="API\Loading\ILoadableObjectSource.cs" />
   15.32 +    <Compile Include="API\Loading\LoadableObjectSourceDirectory.cs" />
   15.33 +    <Compile Include="API\Loading\LoadableObjectSourceResourceSet.cs" />
   15.34    </ItemGroup>
   15.35    <ItemGroup>
   15.36      <Reference Include="System.Xml" />
   15.37 @@ -197,34 +203,35 @@
   15.38    </ProjectExtensions>
   15.39    <ItemGroup>
   15.40      <Folder Include="API\Objects\Requirement\Context\" />
   15.41 +    <Folder Include="API\Loading\" />
   15.42    </ItemGroup>
   15.43    <ItemGroup>
   15.44      <EmbeddedResource Include="schemas\army.xsd">
   15.45 -      <Gettext-ScanForTranslations>false</Gettext-ScanForTranslations>
   15.46 +      <Gettext-ScanForTranslations>False</Gettext-ScanForTranslations>
   15.47      </EmbeddedResource>
   15.48      <EmbeddedResource Include="schemas\race.xsd">
   15.49 -      <Gettext-ScanForTranslations>false</Gettext-ScanForTranslations>
   15.50 +      <Gettext-ScanForTranslations>False</Gettext-ScanForTranslations>
   15.51      </EmbeddedResource>
   15.52      <EmbeddedResource Include="schemas\system.xsd">
   15.53 -      <Gettext-ScanForTranslations>false</Gettext-ScanForTranslations>
   15.54 +      <Gettext-ScanForTranslations>False</Gettext-ScanForTranslations>
   15.55      </EmbeddedResource>
   15.56      <EmbeddedResource Include="schemas\warfoundry-cats.xsd">
   15.57 -      <Gettext-ScanForTranslations>false</Gettext-ScanForTranslations>
   15.58 +      <Gettext-ScanForTranslations>False</Gettext-ScanForTranslations>
   15.59      </EmbeddedResource>
   15.60      <EmbeddedResource Include="schemas\warfoundry-core.xsd">
   15.61 -      <Gettext-ScanForTranslations>false</Gettext-ScanForTranslations>
   15.62 +      <Gettext-ScanForTranslations>False</Gettext-ScanForTranslations>
   15.63      </EmbeddedResource>
   15.64      <EmbeddedResource Include="schemas\xhtml1-strict.dtd">
   15.65 -      <Gettext-ScanForTranslations>false</Gettext-ScanForTranslations>
   15.66 +      <Gettext-ScanForTranslations>False</Gettext-ScanForTranslations>
   15.67      </EmbeddedResource>
   15.68      <EmbeddedResource Include="schemas\xhtml-lat1.ent">
   15.69 -      <Gettext-ScanForTranslations>false</Gettext-ScanForTranslations>
   15.70 +      <Gettext-ScanForTranslations>False</Gettext-ScanForTranslations>
   15.71      </EmbeddedResource>
   15.72      <EmbeddedResource Include="schemas\xhtml-special.ent">
   15.73 -      <Gettext-ScanForTranslations>false</Gettext-ScanForTranslations>
   15.74 +      <Gettext-ScanForTranslations>False</Gettext-ScanForTranslations>
   15.75      </EmbeddedResource>
   15.76      <EmbeddedResource Include="schemas\xhtml-symbol.ent">
   15.77 -      <Gettext-ScanForTranslations>false</Gettext-ScanForTranslations>
   15.78 +      <Gettext-ScanForTranslations>False</Gettext-ScanForTranslations>
   15.79      </EmbeddedResource>
   15.80    </ItemGroup>
   15.81  </Project>
   15.82 \ No newline at end of file