267 lines
9.8 KiB
C#
Raw Normal View History

using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
two commits were missing, both by KorsarNek: "Removed the SupportedPlatformsImpl classes and replaced them with a new SupportedPlatforms attribute on the assembly level. Removed a few class constructors which could cause problems when loading a game. Made ResetElapsedTime in the game class reset to 0 instead of TimeSpan.MinValue. Removed the restriction in the InputDeviceFactory for which InputDevices are supported. Added a Logger for Metro which works with the current Logger implementation. Changed that when a platform is recognized that is higher than Windows 8, it gets treated like Windows 8, not like Windows 7. Due to the SupportedPlatforms change, the assembly loader is now faster in finding out which assemblies contains addIns. For not Metro system, it's also added that a warning gets written if an AddIn references a different ANX version than that of the running assembly. OpenGL and DirectX have been updated to the newest versions. XAudio system uses now the same SharpDX version as all the other systems. ParameterBuffer for WindowsMetro gets now correctly created by considering the size constraints for constant buffers. Fixed an erroneous finalizer in the xaudio system. Made the metro projects convert to Windows 8.1, as Windows 8.0 is not supported by the newer SharpDX versions. It's now also necessary to use at least Visual Studio 2013 to build the Metro versions. Made the samples work again on Windows." "Fixed the creation of the swap chain for windows metro and removed the dependency of the Metro Rendersystem onto the Metro Platformsytem. All occurrences of WindowHandles have been replaced with a custom WindowHandle type which should work out of the box in most cases, but does still represent a breaking change to XNA. The ProjectConverter for Metro was adjusted so that with just changing the way the application is initialized, most projects that worked with ANX before should now work under win rt. The sample SimpleNoContent does now work out of the box for win rt, after a project conversion. The application name for win rt apps is now a guid, the display name stayed the same though. That's to be more compliant with the way win rt apps are normally created. The default namespace and namespace of the classes for the Sample "SimpleNoContent" is renamed from "SimpleModernUI" to "SimpleNoContent". With the new way win rt apps are initialized for ANX, it's necessary to first create the WindowsGameHost for WinRT with a handler how to create the game instance and give that to the CoreApplication object to run it. Also took care of a few annoying bugs when working with win rt and ANX where no InputDevices could be created on the first frame (Issue #1164 ) and that it wasn't possible to use the localfolder of the application on the first update and all the other stuff for which an instance of the Application class was necessary."
2015-03-29 13:48:33 +02:00
using System.Linq;
using ANX.Framework.NonXNA.InputSystem;
namespace ANX.Framework.NonXNA.Reflection
{
internal class AssemblyLoader
{
#region Constants
private static readonly string[] IgnoreAssemblies =
{
"ANX.Framework.dll",
"SharpDX.Direct3D11.Effects.dll",
"OpenTK.dll",
"OpenTK.GLControl.dll",
"OpenTK.Compatibility.dll",
"sharpdx_direct3d11_effects_x86.dll",
"sharpdx_direct3d11_effects_x64.dll",
"SharpDX.dll",
"SharpDX.Direct3D11.dll",
"SharpDX.Direct3D10.dll",
"SharpDX.D3DCompiler.dll",
"SharpDX.DXGI.dll",
"SharpDX.XInput.dll",
"SharpDX.DirectInput.dll",
"WaveUtils.dll",
"SharpDX.XAudio2.dll",
"System.dll",
"System.Core.dll",
"System.Xml.dll",
"System.Xml.Linq.dll",
"mscorlib.dll",
"Sce.PlayStation.Core.dll",
"wrap_oal.dll",
"OpenAL32.dll",
"nunit.framework.dll",
"OggUtils.dll",
"Microsoft.Research.Kinect.dll",
"Microsoft.Xna.Framework.Graphics.dll",
"Microsoft.Xna.Framework.Game.dll",
"Microsoft.Xna.Framework.Content.Pipeline.dll",
"OggUtils.dll",
};
#endregion
#region Private
private List<Assembly> allAssemblies = new List<Assembly>();
private List<Type> creatorTypes = new List<Type>();
private List<Type> supportedPlatformsTypes = new List<Type>();
#endregion
#region Public
public List<Type> CreatorTypes
{
get
{
return creatorTypes;
}
}
public List<Type> SupportedPlatformsTypes
{
get
{
return supportedPlatformsTypes;
}
}
#endregion
public AssemblyLoader()
{
LoadAllAssemblies();
SearchForValidAddInTypes();
}
#region LoadAllAssemblies
private void LoadAllAssemblies()
{
LoadAssembliesFromMemory();
LoadAssembliesFromFile();
LoadAssembliesFromNames();
// Also load the current assembly. This is needed when we run on android or win8 with merged assemblies.
#if !WINDOWSMETRO
var entryAssembly = Assembly.GetEntryAssembly();
//Entry assembly could be null if the managed code was called directly from native code without going through a Main entry point.
//Which would for example happen when the tests are run via NUnit.
if (entryAssembly != null && !allAssemblies.Contains(entryAssembly))
allAssemblies.Add(entryAssembly);
#else
// TODO: a lot of testing is required!
allAssemblies.Add(typeof(AssemblyLoader).GetTypeInfo().Assembly);
#endif
}
#endregion
#region LoadAssembliesFromFile
private void LoadAssembliesFromFile()
{
#if !ANDROID && !WINDOWSMETRO
string executingAssemblyFilepath = Assembly.GetExecutingAssembly().Location;
string basePath = Path.GetDirectoryName(executingAssemblyFilepath);
List<string> assembliesInPath = new List<string>();
assembliesInPath.AddRange(Directory.GetFiles(basePath, "*.dll", SearchOption.TopDirectoryOnly));
assembliesInPath.AddRange(Directory.GetFiles(basePath, "*.exe", SearchOption.TopDirectoryOnly));
foreach (string file in assembliesInPath)
{
bool ignore = false;
foreach (string ignoreName in IgnoreAssemblies)
{
if (Path.GetFileName(file).Equals(ignoreName, StringComparison.InvariantCultureIgnoreCase))
{
ignore = true;
break;
}
}
if (ignore)
continue;
Logger.Info("[ANX] trying to load '" + file + "'...");
try
{
Assembly assembly = Assembly.LoadFrom(file);
if (!allAssemblies.Contains(assembly))
allAssemblies.Add(assembly);
}
catch
{
}
}
#endif
}
#endregion
#region LoadAssembliesFromNames
private void LoadAssembliesFromNames()
{
List<string> allAssemblyNames = new List<string>();
#if WINDOWSMETRO
allAssemblyNames.Add("ANX.PlatformSystem.Metro");
allAssemblyNames.Add("ANX.RenderSystem.Windows.Metro");
allAssemblyNames.Add("ANX.InputSystem.Standard");
allAssemblyNames.Add("ANX.InputDevices.Windows.ModernUI");
allAssemblyNames.Add("ANX.SoundSystem.Windows.XAudio");
#endif
foreach (string assemblyName in allAssemblyNames)
{
Assembly loadedAssembly = LoadAssemblyByName(assemblyName);
if (loadedAssembly != null && !allAssemblies.Contains(loadedAssembly))
allAssemblies.Add(loadedAssembly);
}
}
#endregion
#region LoadAssembliesFromMemory
private void LoadAssembliesFromMemory()
{
foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies())
{
if (!IgnoreAssemblies.Contains(assembly.GetName().Name) && !allAssemblies.Contains(assembly))
allAssemblies.Add(assembly);
}
}
#endregion
#region LoadAssemblyByName
private Assembly LoadAssemblyByName(string assemblyName)
{
try
{
#if WINDOWSMETRO
return Assembly.Load(new AssemblyName(assemblyName));
#else
return Assembly.Load(assemblyName);
#endif
}
catch
{
return null;
}
}
#endregion
#region SearchForValidAddInTypes
private void SearchForValidAddInTypes()
{
foreach (Assembly assembly in allAssemblies)
SearchForValidAddInTypesInAssembly(assembly);
}
#endregion
#region SearchForValidAddInTypesInAssembly
private void SearchForValidAddInTypesInAssembly(Assembly assembly)
{
two commits were missing, both by KorsarNek: "Removed the SupportedPlatformsImpl classes and replaced them with a new SupportedPlatforms attribute on the assembly level. Removed a few class constructors which could cause problems when loading a game. Made ResetElapsedTime in the game class reset to 0 instead of TimeSpan.MinValue. Removed the restriction in the InputDeviceFactory for which InputDevices are supported. Added a Logger for Metro which works with the current Logger implementation. Changed that when a platform is recognized that is higher than Windows 8, it gets treated like Windows 8, not like Windows 7. Due to the SupportedPlatforms change, the assembly loader is now faster in finding out which assemblies contains addIns. For not Metro system, it's also added that a warning gets written if an AddIn references a different ANX version than that of the running assembly. OpenGL and DirectX have been updated to the newest versions. XAudio system uses now the same SharpDX version as all the other systems. ParameterBuffer for WindowsMetro gets now correctly created by considering the size constraints for constant buffers. Fixed an erroneous finalizer in the xaudio system. Made the metro projects convert to Windows 8.1, as Windows 8.0 is not supported by the newer SharpDX versions. It's now also necessary to use at least Visual Studio 2013 to build the Metro versions. Made the samples work again on Windows." "Fixed the creation of the swap chain for windows metro and removed the dependency of the Metro Rendersystem onto the Metro Platformsytem. All occurrences of WindowHandles have been replaced with a custom WindowHandle type which should work out of the box in most cases, but does still represent a breaking change to XNA. The ProjectConverter for Metro was adjusted so that with just changing the way the application is initialized, most projects that worked with ANX before should now work under win rt. The sample SimpleNoContent does now work out of the box for win rt, after a project conversion. The application name for win rt apps is now a guid, the display name stayed the same though. That's to be more compliant with the way win rt apps are normally created. The default namespace and namespace of the classes for the Sample "SimpleNoContent" is renamed from "SimpleModernUI" to "SimpleNoContent". With the new way win rt apps are initialized for ANX, it's necessary to first create the WindowsGameHost for WinRT with a handler how to create the game instance and give that to the CoreApplication object to run it. Also took care of a few annoying bugs when working with win rt and ANX where no InputDevices could be created on the first frame (Issue #1164 ) and that it wasn't possible to use the localfolder of the application on the first update and all the other stuff for which an instance of the Application class was necessary."
2015-03-29 13:48:33 +02:00
var assemblyAttributes = assembly.GetCustomAttributes<SupportedPlatformsAttribute>();
//This step before we are iterating over the types makes the startup faster, around 2 seconds faster.
var supportedPlatforms = assemblyAttributes.SelectMany((x) => x.Platforms).ToArray();
if (supportedPlatforms.Length == 0)
{
#if !WINDOWSMETRO
var ownAssemblyName = TypeHelper.GetAssemblyFrom(typeof(SupportedPlatformsAttribute)).GetName();
Version otherVersion = null;
//If another version is referenced, we can't load our custom attribute.
//Unfortunately it's not possible to check in WinRT if actually the same assembly is referenced.
if (assembly.GetReferencedAssemblies().Any((x) =>
{
otherVersion = x.Version;
return x.Name == ownAssemblyName.Name && x.Version != ownAssemblyName.Version;
}))
{
Logger.Warning(string.Format("Assembly \"{0}\" can't be correctly loaded because it's referencing another ANX.Framework version than the executing assembly. Current: {1}, Foreign: {2}", assembly.FullName, ownAssemblyName.Version, otherVersion), false);
}
else
#endif
{
Logger.Info(string.Format("Skipping assembly \"{0}\" because no supported platforms are specified in the assembly meta data.", assembly.FullName));
}
return;
}
if (!supportedPlatforms.Contains(OSInformation.GetName()))
{
Logger.Info(string.Format("Skipping assembly \"{0}\" because it doesn't support the current platform.", assembly.FullName));
return;
}
Logger.Info("checking assembly \"{0}\".", assembly.FullName);
Type[] allTypes = TypeHelper.SafelyExtractTypesFrom(assembly);
foreach (Type type in allTypes)
{
if (type == null)
throw new TypeLoadException(string.Format("Can't load a type from {0}, maybe a depdency doesn't exist in the correct version.", assembly.FullName));
bool isTypeCreatable = TypeHelper.IsAbstract(type) == false && TypeHelper.IsInterface(type) == false;
two commits were missing, both by KorsarNek: "Removed the SupportedPlatformsImpl classes and replaced them with a new SupportedPlatforms attribute on the assembly level. Removed a few class constructors which could cause problems when loading a game. Made ResetElapsedTime in the game class reset to 0 instead of TimeSpan.MinValue. Removed the restriction in the InputDeviceFactory for which InputDevices are supported. Added a Logger for Metro which works with the current Logger implementation. Changed that when a platform is recognized that is higher than Windows 8, it gets treated like Windows 8, not like Windows 7. Due to the SupportedPlatforms change, the assembly loader is now faster in finding out which assemblies contains addIns. For not Metro system, it's also added that a warning gets written if an AddIn references a different ANX version than that of the running assembly. OpenGL and DirectX have been updated to the newest versions. XAudio system uses now the same SharpDX version as all the other systems. ParameterBuffer for WindowsMetro gets now correctly created by considering the size constraints for constant buffers. Fixed an erroneous finalizer in the xaudio system. Made the metro projects convert to Windows 8.1, as Windows 8.0 is not supported by the newer SharpDX versions. It's now also necessary to use at least Visual Studio 2013 to build the Metro versions. Made the samples work again on Windows." "Fixed the creation of the swap chain for windows metro and removed the dependency of the Metro Rendersystem onto the Metro Platformsytem. All occurrences of WindowHandles have been replaced with a custom WindowHandle type which should work out of the box in most cases, but does still represent a breaking change to XNA. The ProjectConverter for Metro was adjusted so that with just changing the way the application is initialized, most projects that worked with ANX before should now work under win rt. The sample SimpleNoContent does now work out of the box for win rt, after a project conversion. The application name for win rt apps is now a guid, the display name stayed the same though. That's to be more compliant with the way win rt apps are normally created. The default namespace and namespace of the classes for the Sample "SimpleNoContent" is renamed from "SimpleModernUI" to "SimpleNoContent". With the new way win rt apps are initialized for ANX, it's necessary to first create the WindowsGameHost for WinRT with a handler how to create the game instance and give that to the CoreApplication object to run it. Also took care of a few annoying bugs when working with win rt and ANX where no InputDevices could be created on the first frame (Issue #1164 ) and that it wasn't possible to use the localfolder of the application on the first update and all the other stuff for which an instance of the Application class was necessary."
2015-03-29 13:48:33 +02:00
if (isTypeCreatable)
{
bool isTypeValidCreator = TypeHelper.IsTypeAssignableFrom(typeof(ICreator), type);
if (isTypeValidCreator)
{
creatorTypes.Add(type);
two commits were missing, both by KorsarNek: "Removed the SupportedPlatformsImpl classes and replaced them with a new SupportedPlatforms attribute on the assembly level. Removed a few class constructors which could cause problems when loading a game. Made ResetElapsedTime in the game class reset to 0 instead of TimeSpan.MinValue. Removed the restriction in the InputDeviceFactory for which InputDevices are supported. Added a Logger for Metro which works with the current Logger implementation. Changed that when a platform is recognized that is higher than Windows 8, it gets treated like Windows 8, not like Windows 7. Due to the SupportedPlatforms change, the assembly loader is now faster in finding out which assemblies contains addIns. For not Metro system, it's also added that a warning gets written if an AddIn references a different ANX version than that of the running assembly. OpenGL and DirectX have been updated to the newest versions. XAudio system uses now the same SharpDX version as all the other systems. ParameterBuffer for WindowsMetro gets now correctly created by considering the size constraints for constant buffers. Fixed an erroneous finalizer in the xaudio system. Made the metro projects convert to Windows 8.1, as Windows 8.0 is not supported by the newer SharpDX versions. It's now also necessary to use at least Visual Studio 2013 to build the Metro versions. Made the samples work again on Windows." "Fixed the creation of the swap chain for windows metro and removed the dependency of the Metro Rendersystem onto the Metro Platformsytem. All occurrences of WindowHandles have been replaced with a custom WindowHandle type which should work out of the box in most cases, but does still represent a breaking change to XNA. The ProjectConverter for Metro was adjusted so that with just changing the way the application is initialized, most projects that worked with ANX before should now work under win rt. The sample SimpleNoContent does now work out of the box for win rt, after a project conversion. The application name for win rt apps is now a guid, the display name stayed the same though. That's to be more compliant with the way win rt apps are normally created. The default namespace and namespace of the classes for the Sample "SimpleNoContent" is renamed from "SimpleModernUI" to "SimpleNoContent". With the new way win rt apps are initialized for ANX, it's necessary to first create the WindowsGameHost for WinRT with a handler how to create the game instance and give that to the CoreApplication object to run it. Also took care of a few annoying bugs when working with win rt and ANX where no InputDevices could be created on the first frame (Issue #1164 ) and that it wasn't possible to use the localfolder of the application on the first update and all the other stuff for which an instance of the Application class was necessary."
2015-03-29 13:48:33 +02:00
continue;
}
bool isInputCreator = TypeHelper.IsTypeAssignableFrom(typeof(IInputDeviceCreator), type);
if (isInputCreator)
{
var inputCreator = TypeHelper.Create<IInputDeviceCreator>(type);
InputDeviceFactory.Instance.AddCreator(type, inputCreator);
}
}
}
}
#endregion
}
}