AJ's blog

May 5, 2007

(Framework) Extension Points

Filed under: .NET, .NET Framework, ASP.NET, C#, Software Architecture, Software Development — ajdotnet @ 10:19 pm

The web applications I usually build cannot do without session state. Remember that user choice, get complex parameters to the next page, hold this business object until the user finally says “I’m done, save it”.

Session state on the other hand has a poor interface and a big potential for trouble. I therefore usually use a utility class rather than accessing the Session object directly. Call it SessionData, and it’s implemented as a singleton. SessionData would add serveral features, such as type safe getters/setters; optimizations for default values; checking the serializability of the objects to prevent the serialization problem (I may have mentioned it once or twice); getting some statistics about objects in state (number and size). You get the idea. Fairly generic stuff and a good candidate for the next project.

Then I usally add named properties for the project specific session data. And kiss reusability good bye. 😦

Well, I could use another utility class. Another complementary one? No way.
I could derive from SessionData and use is as replacement. Grand idea. But what about my other generic code that may want to access the session state? How would it know about my derived class?

This is a quite common problem for framework developers. Frameworks need means for the user to change or extend their standard behaviour. This usually includes callbacks, events, and virtual methods. In most cases this relies on the ability to run your own code (e.g. to create your instance or to register your calllback) before the change takes effect. If you have a class that overrides a virtual method, someone has to instantiate your derived class. This someone (or rather the first in line) is usually framework code. Code that needs to know the class it instantiates. Code that has no knowledge of your code. Unless you use a factory.

There are two related patterns that allow a framework to work with user code right from the beginning:

  • Provider pattern: used to register a provider class/object that offers some service (e.g. translation) but that does not necessarily have to exist and does not have a default implementation
  • Class substitution: used to replace standard behaviour with customized versions (e.g. session state handling). If it is not replaced, a default implementation will kick in. 

Please note that the pattern names are (c) by AJ.NET. I made them up, so you may come across different names. The license to use the names is fairly simple: You may use them freely. But if you do I want you to stand up and say “I used this word with permission by AJ.NET.” 😀

Provider pattern

The provider pattern is actually quite simple:

  • Some (singleton) object provides access to the actual provider. It uses the factory to instatiate the concrete implementation and handles the case that no provider implementation exists.

public class TranslationProvider
{
    public static ITranslationProvider Current 
    {
        get
        { 
            // use factory to create the instance
            if (_current == null
                _current= (ITranslationProvider)Factory.Current.Create(„ITranslationProvider“);
            return _current;
        }
    }

<object name=“ITranslationProvider“ type=“AJ.Application.Providers.AppTranslationProvider, AJ.Application.Providers“ />

The calling code can ask for the provider and would do nothing if none is present.

Class substitution

Other than the provider pattern, class substitution needs a fully functional default implementation. However it provides the means to replace this standard implementation with a tailored version.

  • A class provides the default implementation
  • Some (singleton) object provides access to the actual instance. It uses the factory to instantiate the concrete implementation and makes sure the standard implementation is used if no other implementation is available.

public class SessionData
{
    public static SessionData Current
    {
        get
        {
            // use factory to create the instance
            if (_current == null)
                _current = (SessionData)Factory.Current.Create(typeof(SessionData).FullName);
            // fall back to default implementation
            if (_current == null)
                _current = new SessionData();
            return _current;
        }
    }
}

public class AppSessionData : SessionData
{
    public static new AppSessionData Current
    {
        get { return (AppSessionData)SessionData.Current; }
    }
    public Guid CurrentSelection
    {
        get { return base.GetString(“CurrentSelection”, string.Empty); }
        set { base.SetString(“CurrentSelection”, value, string.Empty); }
    }
}

<object name=“AJ.Framework.Providers.SessionData“ type=“AJ.Application.Providers.AppSessionData, AJ.Application.Providers“ />

Now the custom type gets created and can be accessed as AppSessionData.Current. While this class offers type safe access to specific session data it is still guaranteed that the framework code accessing session state will use the very same object to do so. And if AppSessionData changed the behaviour of certain methods (e.g. add traces), user code as well as framework code would participate in this change.

BTW: Did you notice? Even the factory is not called directly, rather it uses the class substitution pattern.

This post concludes this little series about factories. Technically I probably didn’t solve very complex issues. Use a factory, work against interfaces, or in the case of class substitution against a base class. That’s about it. The value that goes beyond a technical approach is realized by the patterns: layer separation, mock object support, interception, and extension.

That’s all for now folks,
AJ.NET

kick it on DotNetKicks.com

Advertisement

Leave a Comment »

No comments yet.

RSS feed for comments on this post. TrackBack URI

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

Create a free website or blog at WordPress.com.

%d bloggers like this: