Here’s my idea of simple dependency mapping, without an IoC container. The idea is to drop your binaries into the bin directory, optionally (yes, optionally) name your dependencies somewhere such as in app.config / web.config, and let ‘er rip.
I still hate Castle Windsor, et al, and will never write code around it if I can avoid it.
By the way, this is just DI, not IoC. For IoC without an IoC container, I still like eventing. See my past posts:
Dependency mapping implementation example (conceptual; one can and should use better code than this):
// Scenario infers IMyService as a referenced/shared interface-only type library
// used on both the invoker and the IMyService implementor.
// Example 1:
// match on Type.FullName
IMyService myService = (IMyService)Activator.CreateInstance(
Dependency.GetDependency<IMyService>(ConfigurationManager.AppSettings["myServiceProvider"]));
myConsumer.MyDependency = myService;
// Example 2:
// match on Type.Name case insensitively; NOTE: This is not recommended.
IMyService myOtherService = (IMyService)Activator.CreateInstance(
Dependency.GetDependency<IMyService>(ConfigurationManager.AppSettings["myServiceProvider2"], true));
myConsumer.MyDependency = myOtherService;
// Example 3:
// Only one match? Too lazy to name it? Just take it. NOTE: This is not recommended.
IMyService whateverService = (IMyService)Activator.CreateInstance(
Dependency.GetDependency<IMyService>());
myConsumer.MyDependency = whateverService;
Code:
using System.Reflection; //, etc...
// ...
public class Dependency
{
public static Dictionary<Type, List<Type>> KnownServices
= new Dictionary<Type, List<Type>>();
/// <summary>
/// Returns any <see cref="Type"/> in the current <see cref="AppDomain"/>
/// that is a <typeparamref name="T">T</typeparamref>.
/// </summary>
/// <typeparam name="T">The type in the <see cref="AppDomain"/> that the
/// return <see cref="Type"/> should be or inherit.</typeparam>
/// <returns></returns>
public static object GetDependency<T>()
{
return GetDependency<T>(null);
}
/// <summary>
/// Returns any <see cref="Type"/> in the current <see cref="AppDomain"/>
/// that is a <typeparamref name="T">T</typeparamref>.
/// If <paramref name="by_name"/> is not <code>null</code>, only the type(s) matching
/// the specified <paramref name="by_name"/> with the <see cref="Type.FullName"/> is returned.
/// </summary>
/// <typeparam name="T">The type in the <see cref="AppDomain"/> that the
/// return <see cref="Type"/> should be or inherit.</typeparam>
/// <param name="by_name">The type name that should match the return value(s).</param>
/// <example>object myService = Activator.CreateInstance(GetDependency<IMyService>);</example>
public static object GetDependency<T>(string by_name)
{
return GetDependency<T>(by_name, false);
}
/// <summary>
/// Returns any <see cref="Type"/> in the current <see cref="AppDomain"/>
/// that is a <typeparamref name="T">T</typeparamref>.
/// If <paramref name="by_name"/> is not <code>null</code>, only the type(s) matching
/// the specified name will be returned.
/// </summary>
/// <typeparam name="T">The type in the <see cref="AppDomain"/> that the
/// return <see cref="Type"/> should be or inherit.</typeparam>
/// <param name="by_name">The type name that should match the return value(s).</param>
/// <param name="short_name_case_insensitive">If true, ignores the namespace,
/// casing, and assembly name. For example, a match on type <code>Dog</code>
/// might return both <code>namespace_a.doG</code> and <code>NamespaceB.Dog</code>.
/// Otherwise, a match is made only if the <see cref="Type.FullName"/> matches
/// exactly.
/// </param>
/// <returns>A <see cref="Type"/>.</returns>
/// <example>object myService = Activator.CreateInstance(GetDependency<IMyService>);</example>
public static object GetDependency<T>(string by_name, bool short_name_case_insensitive)
{
if (by_name != null && !short_name_case_insensitive)
{
return Type.GetType(by_name, true);
}
Init<T>();
var t_svcs = KnownServices[typeof(T)];
if (string.IsNullOrEmpty(by_name))
{
if (t_svcs.Count == 0) return null;
if (t_svcs.Count == 1) return t_svcs[0];
return t_svcs; // more than one, return the whole list
}
return t_svcs.Find(t => t.Name.ToLower() == by_name.ToLower());
}
private static readonly Dictionary<Type, bool> Inited = new Dictionary<Type, bool>();
private static void Init<T>()
{
if (Inited.ContainsKey(typeof(T)) && Inited[typeof(T)]) return;
if (!KnownServices.ContainsKey(typeof(T)))
KnownServices.Add(typeof(T), new List<Type>());
var refAssemblies = new List<Assembly>(AppDomain.CurrentDomain.GetAssemblies());
foreach (var assembly in refAssemblies)
{
Type[] types = assembly.GetTypes();
foreach (var type in types)
{
if (type.IsClass && !type.IsAbstract &&
typeof(T).IsAssignableFrom(type))
{
KnownServices[typeof(T)].Add(type);
}
}
}
Inited[typeof(T)] = true;
}
}