using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
namespace Stencil
{
///
/// Stencil is a Basic Inversion of Control Container
///
public class Stencil
{
// Singleton variables
private static Stencil stencil;
private static readonly Options defaults = new Options();
// State
private readonly List interfaces;
///
/// Gets the Stencil Singleton.
///
public static Stencil Instance
{
get
{
if (stencil == null)
{
stencil = new Stencil();
stencil.Initilize(Defaults);
}
return stencil;
}
}
///
/// Gets the default options used to create Stencil singleton.
///
public static Options Defaults
{
get { return defaults; }
}
///
/// Represents an interface in the container
///
private class Interface : ICloneable
{
///
/// Initializes a new instance of the class.
///
/// The type.
public Interface(Type type)
{
Type = type;
}
///
/// Gets or sets the type of this interface.
///
///
/// The type.
///
public Type Type { get; set; }
///
/// Gets or sets the concrete type of this interface.
///
///
/// The type of the concrete.
///
public Type ConcreteType { get; set; }
///
/// Gets or sets the value of the concrete type that implements the interface.
///
///
/// The value.
///
public object Value { get; set; }
///
/// Gets or sets a value indicating whether this instance is a singleton.
///
///
/// true if this instance is a singleton; otherwise, false.
///
public bool IsSingleton { get; set; }
///
/// Gets or sets the order that this interface should be processed when
/// initialized in a list. This value is set by the OrderAttribute.
///
///
/// The order.
///
public int Order { get; set; }
///
/// Determines whether this instance can create the specified type.
///
/// The type.
///
/// true if this instance can create the specified type; otherwise, false.
///
public bool CanCreate(Type type)
{
return Type.IsAssignableFrom(type);
}
///
/// Creates a new object that is a copy of the current instance.
///
///
/// A new object that is a copy of this instance.
///
public object Clone()
{
return new Interface(Type)
{
ConcreteType = ConcreteType,
IsSingleton = IsSingleton,
Value = Value
};
}
}
///
/// Initializes a new instance of the class.
///
public Stencil()
{
interfaces = new List();
}
///
/// Initilizes this instance.
///
public void Initilize()
{
Initilize(Defaults);
}
///
/// Initilizes this instance.
///
public void Initilize(Options options)
{
// Generate interfaces
CreateInterfaces(options.Assemblies);
// Set interface concrete types
CreateInterfaceTypes(options.Assemblies, options.UseSingletons);
}
///
/// Creates the interfaces.
///
/// The assemblies.
private void CreateInterfaces(IEnumerable assemblies)
{
interfaces.Clear();
foreach (var assembly in assemblies)
{
CreateInterfaces(assembly);
}
}
///
/// Creates the interfaces.
///
/// The assembly.
private void CreateInterfaces(Assembly assembly)
{
var types = assembly.GetTypes();
// Parse interfaces
foreach (var type in types)
{
if (!type.IsInterface) continue;
interfaces.Add(new Interface(type));
}
}
private void CreateInterfaceTypes(IEnumerable assemblies, bool useSingletons)
{
foreach (var assembly in assemblies)
{
CreateInterfaceTypes(assembly, useSingletons);
}
}
private void CreateInterfaceTypes(Assembly assembly, bool useSingletons)
{
var types = assembly.GetTypes();
// Parse concrete types
foreach (var type in types)
{
// Skip interfaces
if (type.IsInterface) continue;
// Check is type implements an interface we've processed
foreach (var @interface in interfaces)
{
if (!@interface.CanCreate(type)) continue;
@interface.IsSingleton = useSingletons;
// Assign this concrete type to the interface
if (@interface.ConcreteType == null)
{
@interface.Order = GetOrder(type);
@interface.ConcreteType = type;
}
else
{
// Allow multiple classes to implement the same interface
var clone = (Interface)@interface.Clone();
clone.Order = GetOrder(type);
clone.ConcreteType = type;
@interfaces.Add(clone);
}
break;
}
}
}
private static int GetOrder(Type type)
{
var result = 0;
var attributes = type.GetCustomAttributes(typeof (OrderAttribute), true);
foreach (OrderAttribute attribute in attributes)
{
result = attribute.Order;
}
return result;
}
///
/// Resolves an object of type from this instance.
///
///
///
public T Resolve()
{
return (T)Resolve(typeof(T));
}
///
/// Resolves an object of the specified type from this instance.
///
/// The type.
///
public object Resolve(Type type)
{
return CreateInstance(type);
}
public IList ResolveAll()
{
return ResolveAll(typeof (T)).Select(@object => (T) @object).ToList();
}
public IList