using System; using System.Collections.Generic; using System.Linq; using System.Reflection; namespace BinaryDad.AggregateDal { public class AggregateDataAccess where T : class { private static ICollection dataAccessTypes; static AggregateDataAccess() => LoadInstances(); /// /// Invokes a method for all instances of /// /// /// /// protected TResult Invoke(Func func) { var results = new List(); foreach (var dataAccessType in dataAccessTypes) { var instance = Activator.CreateInstance(dataAccessType) as T; results.Add(func(instance)); } // if the "EF" version invokes first, return that value return results.FirstOrDefault(r => !r.Equals(default(T))); } private static void LoadInstances() { if (dataAccessTypes == null) { var type = typeof(T); var aggregateType = typeof(AggregateDataAccess); // load all types except for 1) the interface itself, 2) any interface, and 3) is not implementing AggregateDataAccess // NOTE: the "EF" version will load first, allowing for the "QuickBase" version to run last, in a separate thread if desired dataAccessTypes = Assembly.GetExecutingAssembly() .ExportedTypes .Where(t => type.IsAssignableFrom(t) && !t.IsInterface && !aggregateType.IsAssignableFrom(t)) .OrderBy(t => t.Name.StartsWith("QuickBase", StringComparison.OrdinalIgnoreCase)) .ToList(); } } } }