public class Loader { public IEnumerable<Type> AllTypes { get; set; } private List<object> allInstances = new List<object>(); public event EventHandler<UnhandledExceptionEventArgs> LoadingError; public void LoadFromFolder(string folder) => AllTypes = Directory.GetFiles(folder, "*.dll").SelectMany(f => { IEnumerable<Type> ts; try { ts = Assembly.LoadFile(f).ExportedTypes; } catch { return Enumerable.Empty<Type>(); } return ts; }); public T Instance<T>() => Instances<T>(false, t => true).FirstOrDefault(); public IEnumerable<T> Instances<T>() => Instances<T>(false, t => true); public T Instance<T>(bool createNew, Func<T, bool> filter) => Instances(createNew, filter).FirstOrDefault(); public IEnumerable<T> Instances<T>(bool createNew, Func<T, bool> filter) { var bt = typeof(T); var ii = bt.IsInterface; return from type in AllTypes where !type.IsInterface && !type.IsAbstract && (ii ? type.GetInterfaces().Contains(bt) : type.IsSubclassOf(bt)) let r = (T)create(type, createNew) where filter(r) select r; } private object create(Type type, bool createNew) { var r = allInstances.FirstOrDefault(i => i.GetType() == type) ?? Activator.CreateInstance(type); if (createNew) { allInstances.Remove(r); } allInstances.Add(r); return r; } }