ABL - The Problem Solver - .Net FAQ
 

Home
Mission
News
Blog
Tools
FAQ
Publications
Downloads
Contact
Contents

 

Frequently asked questions

.NET FAQ Visual FoxPro FAQ

 


Abstract Factories in .NET

One of the very useful design patterns when developing large and flexible applications is the abstract factory.

Just a quick reminder of what an abstract factory is. The definition is: Provide an interface for creating families of related or dependent objects without specifying their concrete classes. So what does this mean? Suppose your code has an order object and needs to generate an invoice. If you are developing a flexible system that can handle changing the invoicing system this would benefit from a factory. Instead of creating an invoicing object directly you can use a factory to determine the correct invoicing object to use.

There are a number of examples of how to do this but the code typically looks something like:

Dim generator As InvoiceGenerator
generator = AbstactFactory.CreateObject(GetType(InvoiceGenerator))
or
generator = AbstactFactory.CreateInvoiceGenerator()

Basically the object is not created through the New operator but through a separate function. This works perfectly well but does mean that you must decide in advance which objects are created through the abstract factory and which are not because they are created in a different way.

However it is possible to use the New operator and still retain the power of the abstract factory. The trick is in the combination of two things. First subclass every class, that needs to be created using the abstract factory, from the ContextBoundObject class. Secondly add a custom attribute to these classes, in my case this is called AbstractFactoryAttribute.

So create the class like this:

<AbstractFactory()> _
Class InvoiceGenerator
    Inherits ContextBoundObject
      ...
End Class

The AbstractFactoryAttribute inherits from ProxyAttribute and needs to implement the CreateInstance() function to create the actual object needed. The function GetClientObjectType() is the one that actually decides which type of object is going to be created.

Imports System.Reflection
Imports System.Runtime.Remoting
Imports System.Runtime.Remoting.Proxies
 
Class AbstractFactoryAttribute
    Inherits ProxyAttribute

    Public Overrides Function CreateInstance( _

        ByVal
serverType As System.Type) As MarshalByRefObject
        Dim obj As MarshalByRefObject
        Dim realType As Type
        realType = GetClientObjectType(serverType)
        obj = AllocateInitializedObject(realType)
        Return obj
    End Function

    Public Shared Function AllocateInitializedObject( _
       
ByVal objectType As Type) As MarshalByRefObject
        Dim obj As MarshalByRefObject
        Dim mi As MethodInfo
        mi = GetType(RemotingServices).GetMethod("AllocateInitializedObject", _
                    BindingFlags.Static Or BindingFlags.NonPublic, _
                    Nothing
, New Type() {GetType(System.Type)}, Nothing)
        obj = CType(mi.Invoke(Nothing, New Object() {objectType}), MarshalByRefObject)
        Return obj
    End Function

    Shared Function GetClientObjectType(ByVal original As Type) As Type
        Dim target As Type
        target = original
        ...
        Return target
    End Function
End Class

Using this system we can create the invoice generator using the following code:

Dim generator As New InvoiceGenerator

Of course the advantage of not having to explicitly code the factory call also means that you can’t see from the object creation if object is created directly or through the factory which can be seen as a disadvantage L of this technique.


 

Send mail to webmaster@TheProblemSolver.nl with questions or comments about this web site.
Copyright © 1995 - 2012 ABL - The Problem Solver
Last modified: December 5th 2011
.NET Events
RSS 2.0