//
// Math.NET Numerics, part of the Math.NET Project
// http://numerics.mathdotnet.com
// http://github.com/mathnet/mathnet-numerics
//
// Copyright (c) 2009-2014 Math.NET
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
//
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
namespace IStation.Numerics.LinearAlgebra.Solvers
{
public static class SolverSetup where T : struct, IEquatable, IFormattable
{
///
/// Loads the available objects from the specified assembly.
///
/// The assembly which will be searched for setup objects.
/// If true, types that fail to load are simply ignored. Otherwise the exception is rethrown.
/// The types that should not be loaded.
public static IEnumerable> LoadFromAssembly(Assembly assembly, bool ignoreFailed = true, params Type[] typesToExclude)
{
#if NETSTANDARD1_3
TypeInfo setupInterfaceType = typeof(IIterativeSolverSetup).GetTypeInfo();
IEnumerable candidates = assembly.DefinedTypes
.Where(typeInfo => !typeInfo.IsAbstract && !typeInfo.IsEnum && !typeInfo.IsInterface && typeInfo.IsVisible)
.Where(setupInterfaceType.IsAssignableFrom)
.Select(typeInfo => typeInfo.GetType());
#else
Type setupInterfaceType = typeof (IIterativeSolverSetup);
IEnumerable candidates = assembly.GetTypes()
.Where(type => !type.IsAbstract && !type.IsEnum && !type.IsInterface && type.IsVisible)
.Where(type => type.GetInterfaces().Any(setupInterfaceType.IsAssignableFrom));
#endif
var setups = new List>();
foreach (var type in candidates)
{
try
{
setups.Add((IIterativeSolverSetup) Activator.CreateInstance(type));
}
catch
{
if (!ignoreFailed)
{
throw;
}
}
}
#if NETSTANDARD1_3
var excludedTypes = new List(typesToExclude.Select(type => type.GetTypeInfo()));
return setups
.Where(s => !excludedTypes.Any(t => t.IsAssignableFrom(s.SolverType.GetTypeInfo()) || t.IsAssignableFrom(s.PreconditionerType.GetTypeInfo())))
.OrderBy(s => s.SolutionSpeed/s.Reliability);
#else
var excludedTypes = new List(typesToExclude);
return setups
.Where(s => !excludedTypes.Any(t => t.IsAssignableFrom(s.SolverType) || t.IsAssignableFrom(s.PreconditionerType)))
.OrderBy(s => s.SolutionSpeed/s.Reliability);
#endif
}
///
/// Loads the available objects from the specified assembly.
///
/// The type in the assembly which should be searched for setup objects.
/// If true, types that fail to load are simply ignored. Otherwise the exception is rethrown.
/// The types that should not be loaded.
public static IEnumerable> LoadFromAssembly(Type typeInAssembly, bool ignoreFailed = true, params Type[] typesToExclude)
{
#if NETSTANDARD1_3
return LoadFromAssembly(typeInAssembly.GetTypeInfo().Assembly, ignoreFailed, typesToExclude);
#else
return LoadFromAssembly(typeInAssembly.Assembly, ignoreFailed, typesToExclude);
#endif
}
///
/// Loads the available objects from the specified assembly.
///
/// The of the assembly that should be searched for setup objects.
/// If true, types that fail to load are simply ignored. Otherwise the exception is rethrown.
/// The types that should not be loaded.
public static IEnumerable> LoadFromAssembly(AssemblyName assemblyName, bool ignoreFailed = true, params Type[] typesToExclude)
{
#if NETSTANDARD1_3
return LoadFromAssembly(Assembly.Load(assemblyName), ignoreFailed, typesToExclude);
#else
return LoadFromAssembly(Assembly.Load(assemblyName.FullName), ignoreFailed, typesToExclude);
#endif
}
///
/// Loads the available objects from the Math.NET Numerics assembly.
///
/// The types that should not be loaded.
public static IEnumerable> Load(Type[] typesToExclude)
{
return LoadFromAssembly(typeof(SolverSetup), false, typesToExclude);
}
///
/// Loads the available objects from the Math.NET Numerics assembly.
///
public static IEnumerable> Load()
{
return LoadFromAssembly(typeof(SolverSetup), false);
}
}
}