// Copyright (c) 2007-2016 CSJ2K contributors. // Licensed under the BSD 3-Clause License. namespace CSJ2K { using System; using System.Collections.Generic; using System.Linq; using System.Reflection; using CSJ2K.Util; /// /// Setup helper methods for initializing library. /// internal static class J2kSetup { /// /// Gets a single instance from the platform assembly implementing the type. /// /// (Abstract) type for which implementation is requested. /// The single instance from the platform assembly implementing the type, /// or null if no or more than one implementations are available. /// It is implicitly assumed that implementation class has a public, parameter-less constructor. internal static T GetSinglePlatformInstance() { try { var assembly = GetCurrentAssembly(); #if NETFX_CORE || NETSTANDARD var type = assembly.DefinedTypes.Single( t => (t.IsSubclassOf(typeof(T)) || typeof(T).GetTypeInfo().IsAssignableFrom(t)) && !t.IsAbstract) .AsType(); #else var type = assembly.GetTypes() .Single(t => (t.IsSubclassOf(typeof(T)) || typeof(T).IsAssignableFrom(t)) && !t.IsAbstract); #endif var instance = (T)Activator.CreateInstance(type); return instance; } catch (Exception) { return default(T); } } /// /// Gets the default classified instance from the platform assembly implementing the type. /// /// (Abstract) type for which implementation is requested. /// The single instance from the platform assembly implementing the type that is classified as default, /// or null if no or more than one default classified implementations are available. /// It is implicitly assumed that all implementation classes has a public, parameter-less constructor. internal static T GetDefaultPlatformInstance() where T : IDefaultable { try { var assembly = GetCurrentAssembly(); var types = GetConcreteTypes(assembly); return GetDefaultOrSingleInstance(types); } catch (Exception) { return default(T); } } private static Assembly GetCurrentAssembly() { #if NETFX_CORE || NETSTANDARD return typeof(J2kSetup).GetTypeInfo().Assembly; #else return typeof(J2kSetup).Assembly; #endif } private static IEnumerable GetConcreteTypes(Assembly assembly) { #if NETFX_CORE || NETSTANDARD return assembly.DefinedTypes.Where( #else return assembly.GetTypes().Where( #endif t => { try { #if NETFX_CORE || NETSTANDARD return (t.IsSubclassOf(typeof(T)) || typeof(T).GetTypeInfo().IsAssignableFrom(t)) && !t.IsAbstract; #else return (t.IsSubclassOf(typeof(T)) || typeof(T).IsAssignableFrom(t)) && !t.IsAbstract; #endif } catch { return false; } #if NETFX_CORE || NETSTANDARD }).Select(t => t.AsType()); #else }); #endif } private static T GetDefaultOrSingleInstance(IEnumerable types) where T : IDefaultable { var instances = types.Select( t => { try { return (T)Activator.CreateInstance(t); } catch { return default(T); } }).ToList(); return instances.Count > 1 ? instances.Single(instance => instance.IsDefault) : instances.SingleOrDefault(); } } }