Made it possible to separate the InputDevices by their provider and set a preffered provider. Otherwise you are restricted to only having one input Device provider. Improved the error message if the WindowHandle on the InputDeviceFactory is invalid. Improved AssemblyLoader which was skipping the InputDevices.OpenTK assembly because the OpenTK assembly was blocked. Added ANX.Framework and SharpDX.Direct3D11.Effects to the ignore list. The AssemblyLoader is not static anymore (Only used in AddinSystemFactory) and it doesn't add the same assembly multiple times anymore. Additionally, if a type of an assembly couldn't be loaded, it throws now a TypeLoadException with the hint that a dependency might have been loaded in the wrong version. Refactored RenderSystem.GL3 with the latest changes on the effect system that have been done in the ANX.Framework.
255 lines
9.4 KiB
C#
255 lines
9.4 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
using System.Reflection;
|
|
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()
|
|
{
|
|
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 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)
|
|
{
|
|
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;
|
|
if (isTypeCreatable)
|
|
{
|
|
bool isTypeValidCreator = TypeHelper.IsTypeAssignableFrom(typeof(ICreator), type);
|
|
if (isTypeValidCreator)
|
|
{
|
|
creatorTypes.Add(type);
|
|
continue;
|
|
}
|
|
|
|
bool isInputCreator = TypeHelper.IsTypeAssignableFrom(typeof(IInputDeviceCreator), type);
|
|
if (isInputCreator)
|
|
{
|
|
var inputCreator = TypeHelper.Create<IInputDeviceCreator>(type);
|
|
InputDeviceFactory.Instance.AddCreator(type, inputCreator);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
#endregion
|
|
}
|
|
}
|