Simple Dependency Mapping

by Jon Davis 19. February 2009 07:19

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&lt;IMyService&gt;);</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&lt;IMyService&gt;);</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;
    }
}

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags:

C# | Software Development

Add comment


(Will show your Gravatar icon)  

  Country flag

biuquote
  • Comment
  • Preview
Loading




 

Powered by BlogEngine.NET 1.4.5.0
Theme by Mads Kristensen

About the author

Jon Davis (aka "stimpy77") has been a programmer, developer, and consultant for web and Windows software solutions professionally since 1997, with experience ranging from OS and hardware support to DHTML programming to IIS/ASP web apps to Java network programming to Visual Basic applications to C# desktop apps.
 
Software in all forms is also his sole hobby, whether playing PC games or tinkering with programming them. "I was playing Defender on the Commodore 64," he reminisces, "when I decided at the age of 12 or so that I want to be a computer programmer when I grow up."

Jon was previously employed as a senior .NET developer at a very well-known Internet services company whom you're more likely than not to have directly done business with. However, this blog and all of jondavis.net have no affiliation with, and are not representative of, his former employer in any way.

Contact Me 


Tag cloud

Calendar

<<  October 2020  >>
MoTuWeThFrSaSu
2829301234
567891011
12131415161718
19202122232425
2627282930311
2345678

View posts in large calendar