anx.framework/ANX.Framework/NonXNA/AddInSystemFactory.cs

265 lines
6.9 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using ANX.Framework.NonXNA.PlatformSystem;
using ANX.Framework.NonXNA.Reflection;
// This file is part of the ANX.Framework created by the
// "ANX.Framework developer group" and released under the Ms-PL license.
// For details see: http://anxframework.codeplex.com/license
namespace ANX.Framework.NonXNA
{
public class AddInSystemFactory
{
#region Constants
internal static readonly Type[] ValidAddInCreators =
{
typeof(IInputSystemCreator),
typeof(IRenderSystemCreator),
typeof(ISoundSystemCreator),
typeof(IMediaSystemCreator),
typeof(IPlatformSystemCreator),
};
#endregion
#region Private
private Dictionary<String, ICreator> creators;
private static AddInSystemFactory instance;
private bool initialized;
private Dictionary<Type, ICreator> defaultCreators;
private Dictionary<AddInType, AddInTypeCollection> addinSystems;
#endregion
#region Public
public static AddInSystemFactory Instance
{
get
{
if (instance == null)
{
instance = new AddInSystemFactory();
Logger.Info("Created AddInSystemFactory instance");
}
return instance;
}
}
internal static IPlatformSystemCreator DefaultPlatformCreator
{
get
{
return Instance.GetDefaultCreator<IPlatformSystemCreator>();
}
}
#endregion
#region Constructor
private AddInSystemFactory()
{
defaultCreators = new Dictionary<Type, ICreator>();
creators = new Dictionary<string, ICreator>();
addinSystems = new Dictionary<AddInType, AddInTypeCollection>();
addinSystems.Add(AddInType.InputSystem, new AddInTypeCollection());
addinSystems.Add(AddInType.MediaSystem, new AddInTypeCollection());
addinSystems.Add(AddInType.RenderSystem, new AddInTypeCollection());
addinSystems.Add(AddInType.SoundSystem, new AddInTypeCollection());
addinSystems.Add(AddInType.PlatformSystem, new AddInTypeCollection());
Logger.Info("Operating System: {0} ({1})", OSInformation.GetVersionString(),
OSInformation.GetVersion().ToString());
}
#endregion
#region Initialize
public void Initialize()
{
if (initialized == false)
{
initialized = true;
Logger.Info("[ANX] Initializing ANX.Framework AddInSystemFactory...");
CreateAllAddIns();
SortAddIns();
}
}
#endregion
#region CreateAllAddIns
private void CreateAllAddIns()
{
Assembly[] allAssemblies = AssemblyLoader.GetAllAssemblies();
foreach (Assembly assembly in allAssemblies)
{
AddIn addin = new AddIn(assembly);
if (addin.IsValid && addin.IsSupported)
{
addinSystems[addin.Type].AvailableSystems.Add(addin);
Logger.Info("[ANX] successfully loaded addin...");
}
else
{
Logger.Info("[ANX] skipped loading file because it is not supported or not a valid AddIn");
}
}
}
#endregion
#region AddCreator
public void AddCreator(ICreator creator)
{
string creatorName = creator.Name.ToLowerInvariant();
if (creators.ContainsKey(creatorName))
{
throw new Exception("Duplicate creator found. A creator with the name '" +
creator.Name + "' was already registered.");
}
creators.Add(creatorName, creator);
Logger.Info("added creator '{0}'. Total count of registered creators is now {1}.", creatorName, creators.Count);
}
#endregion
#region HasFramework
public bool HasFramework(String name)
{
return creators.ContainsKey(name.ToLowerInvariant());
}
#endregion
#region GetCreator
public T GetCreator<T>(String name) where T : class, ICreator
{
Initialize();
ICreator creator = null;
creators.TryGetValue(name.ToLowerInvariant(), out creator);
return creator as T;
}
#endregion
#region GetCreators
public IEnumerable<T> GetCreators<T>() where T : class, ICreator
{
Initialize();
foreach (ICreator creator in creators.Values)
{
Type[] interfaces = TypeHelper.GetInterfacesFrom(creator.GetType());
foreach (Type t in interfaces)
{
if (t.Name.Equals( typeof(T).Name ))
{
yield return creator as T;
}
}
}
}
#endregion
#region GetDefaultCreator
public T GetDefaultCreator<T>() where T : class, ICreator
{
Initialize();
AddInType addInType = GetAddInType(typeof(T));
AddInTypeCollection info = addinSystems[addInType];
if (String.IsNullOrEmpty(info.PreferredName))
{
if (info.AvailableSystems.Count > 0)
{
return info.AvailableSystems[0].Instance as T;
}
throw new AddInLoadingException(String.Format(
"Couldn't get default {0} because there are no " +
"registered {0}s available! Make sure you referenced a {0} library " +
"in your project or one is laying in your output folder!", addInType));
}
else
{
foreach (AddIn addin in info.AvailableSystems)
{
if (addin.Name.Equals(info.PreferredName,
StringComparison.CurrentCultureIgnoreCase))
{
return addin.Instance as T;
}
}
throw new AddInLoadingException(String.Format(
"Couldn't get default {0} '{1}' because it was not found in the " +
"list of registered creators!", addInType, info.PreferredName));
}
throw new AddInLoadingException(String.Format(
"Couldn't find a DefaultCreator of type '{0}'!", typeof(T).FullName));
}
#endregion
#region SortAddIns
public void SortAddIns()
{
foreach (AddInTypeCollection info in addinSystems.Values)
{
info.AvailableSystems.Sort();
}
creators = creators.OrderBy(x => x.Value.Priority).ToDictionary(
x => x.Key, x => x.Value);
}
#endregion
#region GetPreferredSystem
public string GetPreferredSystem(AddInType addInType)
{
return addinSystems[addInType].PreferredName;
}
#endregion
#region SetPreferredSystem
public void SetPreferredSystem(AddInType addInType, string preferredName)
{
if (addinSystems[addInType].PreferredLocked)
{
throw new AddInLoadingException(String.Format(
"Can't set preferred {0} because a {0} is alread in use.", addInType));
}
addinSystems[addInType].PreferredName = preferredName;
}
#endregion
#region PreventSystemChange
public void PreventSystemChange(AddInType addInType)
{
addinSystems[addInType].PreferredLocked = true;
}
#endregion
#region GetAddInType
internal static AddInType GetAddInType(Type t)
{
foreach (Type creatorType in ValidAddInCreators)
{
if (TypeHelper.IsTypeAssignableFrom(creatorType, t))
{
return (AddInType)Enum.Parse(typeof(AddInType),
creatorType.Name.Substring(1, creatorType.Name.Length - 8));
}
}
return AddInType.Unknown;
}
#endregion
}
}