Click here to Skip to main content
12,401,608 members (55,662 online)
Click here to Skip to main content

Stats

13.7K views
160 downloads
16 bookmarked
Posted

Dynamic Binding Using the Factory Pattern

, 1 Nov 2009 CPOL
Using the Factory design pattern to hide dynamic binding and use configuration strings to determine which classes should be instantiated.
/*************************************************************************
 *
 * Copyright 2009 Richard (Rick) Marvin Wycoff, All Rights Reserved
 * DO NOT ALTER OR REMOVE THIS COPYRIGHT NOTICE.
 *
 * NOTICE: You are permitted to use, modify, and distribute this file in 
 * accordance with the terms of the license agreement accompanying it.  
 * Any existing copyright or authorship information in any given source
 * file must remain intact.
 *
 **************************************************************************/

using System;
using System.Collections.Generic;
using System.Linq;

namespace Wycoff.Activation
{
    /// <summary>
    /// Manages how instances of a class are loaded into the process space
    /// using a Uri to specify the binding.  The format of the Uri depends
    /// on the type of activiation that will be used.  Activators provied the
    /// required implementation to load the class into the process space.
    /// Activators are derived from Locator.ILocatorActivator interface.  Some
    /// Activators do not allow passing c'tor parameters.  In these cases,
    /// the Locator.IDelayedInitializer interface can be used to initialize
    /// the object after the default c'tor has been used to construct the
    /// object.
    /// </summary>
    public class Locator
    {
        /// <summary>
        /// Activators provide the implementation required to load a class
        /// into the current process.  All Activators must implement this
        /// interface and be registered with the the Locator class.
        /// <remarks>
        /// There are differening style oppinions on nesting interfaces in
        /// this manner.  In this case, I chose to nest it in this because 
        /// the interface is ONLY related to Activator functionality within 
        /// the context of a Locator.  Any other use (at this point) would be 
        /// deemed inappropriate.<br /><br />
        /// Follow the your established coding conventions.  If you don't have
        /// any, then find some.
        /// </remarks>
        /// </summary>
        public interface ILocatorActivator
        {
            /// <summary>
            /// Creates and instance of the requested object (or proxy) in
            /// the current process space.
            /// </summary>
            /// <param name="type">
            /// The type of the object (or interface) that is being requested.
            /// </param>
            /// <param name="uri">
            /// Locator Uri
            /// </param>
            /// <returns>
            /// Instance of the object, interface, or proxy.
            /// </returns>
            object Activate(Type type, Uri uri);
        }

        /// <summary>
        /// Dictionary of locator keys and an instance of the Activator class
        /// that will process the locator Uri.
        /// </summary>
        private static Dictionary<string, ILocatorActivator> _activators
            = new Dictionary<string, ILocatorActivator>();

        /// <summary>
        /// Static c'tor that registers the default Activators.
        /// </summary>
        static Locator()
        {
            RegisterActivator("local", new InProcessActivator());
            RegisterActivator("tcp", new SaoActivator());
        }

        /// <summary>
        /// Regsiters a Activator and the associated locator key.  The locator
        /// key occupies the protocol portion of the Uri.  Note that an
        /// Activator may change the protocol of the Uri to the correct "real"
        /// value in order to bind to the object.
        /// </summary>
        /// <param name="protocol">
        /// The locator key for this Activator.
        /// </param>
        /// <param name="activator">
        /// Instance of an Activator that will process these locator requests.
        /// </param>
        public static void RegisterActivator(string scheme, ILocatorActivator activator)
        {
            if (_activators.Keys.Contains(scheme.ToLower()))
            {
                throw new ArgumentException(scheme);
            }
            else
            {
                _activators.Add(scheme.ToLower(), activator);
            }
        }

        /// <summary>
        /// Establishes a binding to a new instance of the class specified
        /// by the locator string (Uri).
        /// </summary>
        /// <param name="type">
        /// The desired type.
        /// </param>
        /// <param name="locator">
        /// The locator string (Uri).
        /// </param>
        /// <returns>
        /// An instance of the object (or proxy).  If not Activator is
        /// found, returns null.
        /// </returns>
        public static object Activate(Type type, string locator)
        {
            object response = null;

            Uri uri = new Uri(locator);
            if (_activators.Keys.Contains(uri.Scheme.ToLower()))
            {
                ILocatorActivator activator = _activators[uri.Scheme.ToLower()];
                response = activator.Activate(type, uri);
            }

            return response;
        }
    }
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Richard (Rick) Wycoff
Software Developer (Senior)
United States United States
Rick's software passion is developing "invisible” software components, the kind that no one ever thinks about because they just do what they are supposed to do. He believes in standards, design patterns, and designing components for extensibility and reuse.

You may also be interested in...

| Advertise | Privacy | Terms of Use | Mobile
Web02 | 2.8.160721.1 | Last Updated 1 Nov 2009
Article Copyright 2009 by Richard (Rick) Wycoff
Everything else Copyright © CodeProject, 1999-2016
Layout: fixed | fluid