Skip to content

Instantly share code, notes, and snippets.

@DevJohnC
Created June 18, 2014 22:54
Show Gist options
  • Save DevJohnC/56a73e282c8179b98531 to your computer and use it in GitHub Desktop.
Save DevJohnC/56a73e282c8179b98531 to your computer and use it in GitHub Desktop.
//
// Author: John Carruthers ([email protected])
//
// Copyright (C) 2014 John Carruthers
//
// 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.Reflection;
using AdjutantFramework.Modules.Domains;
namespace AdjutantFramework.Modules
{
/// <summary>
/// Collection of ILoader(T) with their associated domain managers.
/// </summary>
public class LoaderCollection
{
private readonly List<LoaderContainer> _loaderContainers = new List<LoaderContainer>();
/// <summary>
/// Adds a module loader to the collection with the domain manager to use when loading modules.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="loader">Module loader.</param>
/// <param name="domainManager">Domain manager to use when loading modules.</param>
public void Add<T>(ILoader<T> loader, IManager domainManager) where T : IModuleDefinition
{
lock (_loaderContainers)
{
_loaderContainers.Add(new LoaderContainer
{
Loader = loader,
ModuleDefinitionType = typeof(T),
Manager = domainManager,
AvailableModulesGetter = loader.GetType().GetProperty("AvailableModules").GetGetMethod()
});
}
}
/// <summary>
/// Gets the domain manager associated with the module loader.
/// </summary>
/// <param name="loader"></param>
/// <returns></returns>
public IManager GetManager(object loader)
{
lock (_loaderContainers)
{
foreach (var container in _loaderContainers)
{
if (container.Loader == loader)
return container.Manager;
}
}
return null;
}
/// <summary>
/// Enumerates available modules.
/// </summary>
public IEnumerable<ModuleInfo> AvailableModules
{
get
{
lock (_loaderContainers)
{
var exceptionList = new List<Exception>();
foreach (var container in _loaderContainers)
{
foreach (var module in container.AvailableModules)
{
yield return new ModuleInfo { Loader = container.Loader, Definition = module };
}
}
if (exceptionList.Count > 0)
throw new AggregateException("One or more module definitions threw exceptions.", exceptionList);
}
}
}
}
public class ModuleInfo
{
public object Loader { get; set; }
public IModuleDefinition Definition { get; set; }
}
internal class LoaderContainer
{
public object Loader { get; set; }
public Type ModuleDefinitionType { get; set; }
public IManager Manager { get; set; }
public MethodInfo AvailableModulesGetter { get; set; }
public IEnumerable<IModuleDefinition> AvailableModules
{
get { return AvailableModulesGetter.Invoke(Loader, new object[0]) as IEnumerable<IModuleDefinition>; }
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment