| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243 | 
							- namespace Caliburn.Micro.Core {
 
-     using System;
 
-     using System.Collections;
 
-     using System.Collections.Generic;
 
-     using System.Linq;
 
-     using System.Reflection;
 
-     /// <summary>
 
-     ///   A simple IoC container.
 
-     /// </summary>
 
-     public class SimpleContainer {
 
-         static readonly Type delegateType = typeof(Delegate);
 
-         static readonly Type enumerableType = typeof(IEnumerable);
 
-         readonly List<ContainerEntry> entries;
 
-         /// <summary>
 
-         ///   Initializes a new instance of the <see cref = "SimpleContainer" /> class.
 
-         /// </summary>
 
-         public SimpleContainer() {
 
-             entries = new List<ContainerEntry>();
 
-         }
 
-         SimpleContainer(IEnumerable<ContainerEntry> entries) {
 
-             this.entries = new List<ContainerEntry>(entries);
 
-         }
 
-         /// <summary>
 
-         ///   Registers the instance.
 
-         /// </summary>
 
-         /// <param name = "service">The service.</param>
 
-         /// <param name = "key">The key.</param>
 
-         /// <param name = "implementation">The implementation.</param>
 
-         public void RegisterInstance(Type service, string key, object implementation) {
 
-             RegisterHandler(service, key, container => implementation);
 
-         }
 
-         /// <summary>
 
-         ///   Registers the class so that a new instance is created on every request.
 
-         /// </summary>
 
-         /// <param name = "service">The service.</param>
 
-         /// <param name = "key">The key.</param>
 
-         /// <param name = "implementation">The implementation.</param>
 
-         public void RegisterPerRequest(Type service, string key, Type implementation) {
 
-             RegisterHandler(service, key, container => container.BuildInstance(implementation));
 
-         }
 
-         /// <summary>
 
-         ///   Registers the class so that it is created once, on first request, and the same instance is returned to all requestors thereafter.
 
-         /// </summary>
 
-         /// <param name = "service">The service.</param>
 
-         /// <param name = "key">The key.</param>
 
-         /// <param name = "implementation">The implementation.</param>
 
-         public void RegisterSingleton(Type service, string key, Type implementation) {
 
-             object singleton = null;
 
-             RegisterHandler(service, key, container => singleton ?? (singleton = container.BuildInstance(implementation)));
 
-         }
 
-         /// <summary>
 
-         ///   Registers a custom handler for serving requests from the container.
 
-         /// </summary>
 
-         /// <param name = "service">The service.</param>
 
-         /// <param name = "key">The key.</param>
 
-         /// <param name = "handler">The handler.</param>
 
-         public void RegisterHandler(Type service, string key, Func<SimpleContainer, object> handler) {
 
-             GetOrCreateEntry(service, key).Add(handler);
 
-         }
 
-         /// <summary>
 
-         ///   Unregisters any handlers for the service/key that have previously been registered.
 
-         /// </summary>
 
-         /// <param name = "service">The service.</param>
 
-         /// <param name = "key">The key.</param>
 
-         public void UnregisterHandler(Type service, string key) {
 
-             var entry = GetEntry(service, key);
 
-             if (entry != null) {
 
-                 entries.Remove(entry);
 
-             }
 
-         }
 
-         /// <summary>
 
-         ///   Requests an instance.
 
-         /// </summary>
 
-         /// <param name = "service">The service.</param>
 
-         /// <param name = "key">The key.</param>
 
-         /// <returns>The instance, or null if a handler is not found.</returns>
 
-         public object GetInstance(Type service, string key) {
 
-             var entry = GetEntry(service, key);
 
-             if (entry != null) {
 
-                 return entry.Single()(this);
 
-             }
 
-             if (service == null) {
 
-                 return null;
 
-             }
 
-             if (delegateType.IsAssignableFrom(service)) {
 
-                 var typeToCreate = service.GetGenericArguments()[0];
 
-                 var factoryFactoryType = typeof(FactoryFactory<>).MakeGenericType(typeToCreate);
 
-                 var factoryFactoryHost = Activator.CreateInstance(factoryFactoryType);
 
-                 var factoryFactoryMethod = factoryFactoryType.GetMethod("Create", new Type[] { typeof(SimpleContainer) });
 
-                 return factoryFactoryMethod.Invoke(factoryFactoryHost, new object[] { this });
 
-             }
 
-             if (enumerableType.IsAssignableFrom(service) && service.IsGenericType()) {
 
-                 var listType = service.GetGenericArguments()[0];
 
-                 var instances = GetAllInstances(listType).ToList();
 
-                 var array = Array.CreateInstance(listType, instances.Count);
 
-                 for (var i = 0; i < array.Length; i++) {
 
-                     array.SetValue(instances[i], i);
 
-                 }
 
-                 return array;
 
-             }
 
-             return null;
 
-         }
 
-         /// <summary>
 
-         /// Determines if a handler for the service/key has previously been registered.
 
-         /// </summary>
 
-         /// <param name="service">The service.</param>
 
-         /// <param name="key">The key.</param>
 
-         /// <returns>True if a handler is registere; false otherwise.</returns>
 
-         public bool HasHandler(Type service, string key) {
 
-             return GetEntry(service, key) != null;
 
-         }
 
-         /// <summary>
 
-         ///   Requests all instances of a given type.
 
-         /// </summary>
 
-         /// <param name = "service">The service.</param>
 
-         /// <returns>All the instances or an empty enumerable if none are found.</returns>
 
-         public IEnumerable<object> GetAllInstances(Type service) {
 
-             var entry = GetEntry(service, null);
 
-             return entry != null ? entry.Select(x => x(this)) : new object[0];
 
-         }
 
-         /// <summary>
 
-         ///   Pushes dependencies into an existing instance based on interface properties with setters.
 
-         /// </summary>
 
-         /// <param name = "instance">The instance.</param>
 
-         public void BuildUp(object instance) {
 
-             var injectables = from property in instance.GetType().GetProperties()
 
-                               where property.CanRead && property.CanWrite && property.PropertyType.IsInterface()
 
-                               select property;
 
-             foreach (var propertyInfo in injectables) {
 
-                 var injection = GetAllInstances(propertyInfo.PropertyType).ToArray();
 
-                 if (injection.Any()) {
 
-                     propertyInfo.SetValue(instance, injection.First(), null);
 
-                 }
 
-             }
 
-         }
 
-         /// <summary>
 
-         /// Creates a child container.
 
-         /// </summary>
 
-         /// <returns>A new container.</returns>
 
-         public SimpleContainer CreateChildContainer() {
 
-             return new SimpleContainer(entries);
 
-         }
 
-         ContainerEntry GetOrCreateEntry(Type service, string key) {
 
-             var entry = GetEntry(service, key);
 
-             if (entry == null) {
 
-                 entry = new ContainerEntry { Service = service, Key = key };
 
-                 entries.Add(entry);
 
-             }
 
-             return entry;
 
-         }
 
-         ContainerEntry GetEntry(Type service, string key) {
 
-             if (service == null) {
 
-                 return entries.FirstOrDefault(x => x.Key == key);
 
-             }
 
-             if (key == null) {
 
-                 return entries.FirstOrDefault(x => x.Service == service && x.Key == null)
 
-                        ?? entries.FirstOrDefault(x => x.Service == service);
 
-             }
 
-             return entries.FirstOrDefault(x => x.Service == service && x.Key == key);
 
-         }
 
-         /// <summary>
 
-         ///   Actually does the work of creating the instance and satisfying it's constructor dependencies.
 
-         /// </summary>
 
-         /// <param name = "type">The type.</param>
 
-         /// <returns></returns>
 
-         protected object BuildInstance(Type type) {
 
-             var args = DetermineConstructorArgs(type);
 
-             return ActivateInstance(type, args);
 
-         }
 
-         /// <summary>
 
-         ///   Creates an instance of the type with the specified constructor arguments.
 
-         /// </summary>
 
-         /// <param name = "type">The type.</param>
 
-         /// <param name = "args">The constructor args.</param>
 
-         /// <returns>The created instance.</returns>
 
-         protected virtual object ActivateInstance(Type type, object[] args) {
 
-             var instance = args.Length > 0 ? System.Activator.CreateInstance(type, args) : System.Activator.CreateInstance(type);
 
-             Activated(instance);
 
-             return instance;
 
-         }
 
-         /// <summary>
 
-         ///   Occurs when a new instance is created.
 
-         /// </summary>
 
-         public event Action<object> Activated = delegate { };
 
-         object[] DetermineConstructorArgs(Type implementation) {
 
-             var args = new List<object>();
 
-             var constructor = SelectEligibleConstructor(implementation);
 
-             if (constructor != null)
 
-                 args.AddRange(constructor.GetParameters().Select(info => GetInstance(info.ParameterType, null)));
 
-             return args.ToArray();
 
-         }
 
-         static ConstructorInfo SelectEligibleConstructor(Type type) {
 
-             return (from c in type.GetConstructors().Where(c => c.IsPublic)
 
-                     orderby c.GetParameters().Length descending
 
-                     select c).FirstOrDefault();
 
-         }
 
-         class ContainerEntry : List<Func<SimpleContainer, object>> {
 
-             public string Key;
 
-             public Type Service;
 
-         }
 
-         class FactoryFactory<T> {
 
-             public Func<T> Create(SimpleContainer container) {
 
-                 return () => (T)container.GetInstance(typeof(T), null);
 
-             }
 
-         }
 
-     }
 
- }
 
 
  |