Skip to content

Dynamic Behaviors With Static Typing

I stick with static typing because of its programming to interface (client contract). I am attracted by dynamic typing with its ability to add behaviors at runtime. Unfortunately, you can only have one or the other but not both. Even mixing them in one language like C# (.NET 4 has some dynamic typing capabilities now), you lose the capability to have dynamic behaviors when you use static typing, and you lose programming to contract when you use dynamic typing. Or is it?

Dynamic Behaviors With Static Typing

The reason for dynamic typing to be able to add dynamic behaviors at runtime is that it works directly with objects without involving classes (remember, no class in dynamic typing). In the blog Adapt to Changes With Dynamic Behaviors, I pointed out that dynamic typing is sufficient but not necessary for dynamic behaviors. In static typing, we can directly work with objects, too. That is what Component-Based Object Extender (CBO Extender) does.

CBO Extender is an object extensibility framework for .NET and works directly with objects and interfaces. It does not know or care, and is completely decoupled from, components from which objects are created. Any interface methods can be decorated with extra behaviors at runtime. Cross-cutting concerns like logging, security checking or transaction management can be presented as dynamic behaviors which are added to objects at runtime as needed (see article Dynamic Object Programming for examples). Business requirements like sorting or anything (e.g., Hello World!) can also be presented as dynamic behaviors which are added to objects at runtime (see articles Application Development With Component-Based Object Extender and OOP, AOP and OP).

You now end up with best of both worlds: programming to interface and dynamic behaviors. You use static typing to define your interfaces, classes and components. An application developer can expect a software component with core business functionality and well-defined client contract (interfaces). He/She can use CBO Extender to add extra functionality to objects of the component as needed at runtime.

To see how easy you can add dynamic behaviors to an application, here, I resue the Hello World! example presented in the blog OOP, AOP and OP.

Say, you have a DoAnything component that implements an IDoAnything interface. The application code is listed as follows.

namespace HelloWorld
{
    public interface IDoAnything
    {
        void DoThing();
    }

    public class DoAnything : IDoAnything
    {
        public void DoThing()
        {
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            IDoAnything doAThing = new DoAnything();

            doAThing.DoThing();
        }
    }
}

Of course, the DoThing method of doAThing object does nothing. Now, let’s define a SayHello aspect method and a SayBye method, and use ObjectProxyFactory.CreateProxy2 method of CBO Extender to add them to the doAThing object as extra behaviors. The application is listed as follows.

using CBOExtender;

namespace HelloWorld
{
    public interface IDoAnything
    {
        void DoThing();
    }

    public class DoAnything : IDoAnything
    {
        public void DoThing()
        {
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            IDoAnything doAThing = new DoAnything();

            doAThing = ObjectProxyFactory.CreateProxy2<IDoAnything>(
                doAThing,
                new string[] { "DoThing" },
                new Decoration2(SayHello, null),
                new Decoration2(SayBye, null)
            );

            doAThing.DoThing();
        }

        public static void SayHello(AspectContext2 ctx, dynamic parameters)
        {
            System.Console.WriteLine("Hello World!");
        }

        public static void SayBye(AspectContext2 ctx, dynamic parameters)
        {
            System.Console.WriteLine("Bye!");
        }
    }
}

Now, the DoThing method of doAThing object outputs the “Hello World!” and “Bye!”.

Actually, there is nothing that can stop you to put any logic into the SayHello method or SayBye method. You can also create any number of objects of DoAnything and add any number of aspect methods. Your DoAnything component indeed can do anything!

Advertisements

Adapt To Changes With Dynamic Behaviors

Requirements are moving targets. It is hard for a static programming language to keep up with changes of requirements of a software system. Interestingly, we have seen increasing efforts to make C# programming language more dynamic with dynamic keyword in C# and ExpandoObject type in .NET 4.0.

With Component-Based Object Extender (CBO Extender), an object extensibility framework for .NET, behaviors can be added to object at runtime. It makes a software system more flexible and adaptive to changes.

Static Typing, Dynamic Typing and Dynamic Behaviors

Static typing is class-based programming in which a class has to be defined at design time prior to an object can be created out of it and used. In class design, methods are molded into classes, which is both a blessing and curse. On the brighter side, molding methods into classes is at the core of objects being able to receive messages and the ability to define standard protocols. On the darker side, explicitly molding every single method to a specific class leads to programs that are rigid and hard to evolve and maintain. Static typing is facing serious challenges from today’s constantly changing business requirements while software systems are continuously getting bigger and more complicate.

Dynamic typing is prototype-based programming in which classes are not present, and behavior reuse is performed via a process of cloning existing objects that serve as prototypes. With dynamic typing, you can add, delete or alter methods of an object at runtime anywhere in a program. It is so flexible that it is hard to maintain correctness, safety and predictability in a large software system. It does not seem to be a good solution to the challenges that static typing is facing.

Then, how can we make the class-based programming more dynamic without sacrificing its strengths? Well, if you think about the dynamic typing a bit more, you will find ultimately what we need from dynamic typing is its ability to add behaviors at runtime (dynamic behaviors). However, it does not mean that dynamic behaviors can only be provided by dynamic typing. Proxy-based programming can, too, add behaviors at runtime by decorating methods of object. In proxy-based programming, a dynamic decorator is used to attach behaviors to an object and returns a proxy of the object. To client of the object, the proxy is still the same type and is used as if it was the original object.

Proxy-based programming complements class-based programming with dynamic behaviors, which makes a software system more flexible and readily adpative to changes without involving dynamic typing. With class-based programming, an application developer can expect a software component with core business functionality and well-defined client contract (interfaces). With proxy-based programming, the application developer can add extra functionality to objects of the component as needed at runtime.

Dynamic Behaviors with CBO Extender

Perhaps, one of most important accomplishments coming out of class-based programming is the concept of interface (client contract). With interface, a client does not need to know about the inner workings of a component in order to make use of it. By programming to interface, the client is completely decoupled from the implementation of a component. Consequently, a component can replace another (at design time or runtime) as long as the successor component implements the same interface as the initial component without breaking the system in which the component operates.

CBO Extender is proxy-based and uses programming to interface. With CBO Extender, you define a set of aspect methods to represent behaviors based on your business or system requirements. These behaviors, then, can be used to decorate object’s methods as needed in your application using its Dynamic Decorator or AOP Container.

CBO Extender works directly with objects and interfaces. It does not know or care, and is completely decoupled from, the classes from which objects are created. Any interface methods can be decorated with extra behaviors at runtime. Cross-cutting concerns like logging, security checking or transaction management can be presented as dynamic behaviors which are added to objects at runtime as needed (see article Dynamic Object Programming for examples). Business requirements like sorting or anything (e.g., Hello World!) can also be presented as dynamic behaviors which are added to objects at runtime (see articles Application Development With Component-Based Object Extender and OOP, AOP and OP).

Conculsion

  • Mixing dynamic typing with static typing does not solve the rigidity associated with class-based programming.
  • Proxy-based programming complements class-based programming with dynamic behaviors.
  • Dynamic behaviors make software system flexible and adaptive to changes.

Class Programming Where Possible, Object Programming When Needed

Although C# is a static programming language, with object programming (OP), extra behaviors can be added to objects at runtime. We now are a little closer to the ideal world – Static Typing Where Possible, Dynamic Typing When Needed.

What is Wrong with Static Typing

The most critics to static typing come from its rigidity and inflexibility to requirement changes. The rigidity and inflexibility is due to the lack of mechanism to alter objects at runtime. A class has to be defined at design time prior to an object can be created out of it and used. An object behaves as defined in its class, no more and no less. On the other hand, with dynamic typing an object can be created without class and can be altered at runtime.

Even though we need to define a class to create an object in a static typing language, the situations can be alleviated if object’s behaviors can be enhanced at runtime. That is what the object programming is about. With object programming, a set of behaviors are defined as methods based on business and system requirements. These behaviors are, then, attached to objects as needed in an application. At runtime, the attached behaviors are performed before and/or after the invocation of the object’s methods.

Class Programming and Object Programming

Class Programming (CP) is static typing programming. It is everything we do today with a static programming language: define classes, create objects of the classes and then use the objects.

On the other hand, the object programming (OP) is an answer to the critics on static typing’s rigidity and inflexibility. However, instead of altering an object like in dynamic typing languages, the object programming attaches extra behaviors to an object and returns a proxy of the object. To client of the object, the proxy is still the same type and is used as if it was the original object.

Now that we have two programming paradigms to choose, which one should we use and when to use it? Well, class programming is a code translation and abstraction of OOA/OOD. Since OOA/OOD are excellent for modeling business entities and business processes, the class programming excels at breaking a system down into business components and describing business processes through them. However, besides business requirements, a software system should also have other capabilities like logging, security, auditing, transaction management, etc. and adapt to requirement changes. These issues are not addressed by OOA/OOD, and therefere, can not be solved effectively by class programming. That is why the object programming comes in handy. Since these issues are dynamic in nature, they can be translated into a set of methods and attached to objects at runtime. Therefore, in the software development life cycle (SDLC), the class programming can be used to define business components and simulate business processes through them. It should be very clear that business components should only implement business logic and avoid change once released. Then, the object programming can be used to address other issues and response to requirement changes at runtime as needed.

With class programming, an application developer can expect a software component with core business functionality and well-defined client contract (interfaces). With object programming, the application developer can add extra functionality to objects of the component as needed at runtime. That is what we mean by “Class Programming Where Possible, Object Programming When Needed!”

Object programming is particularly suitable to address cross-cutting concerns and adaptive to changes of a software system. Please refer to OOP, AOP and OP to see how object programming addresses these issues. To see how an application can be enhanced with functionality like logging, security checking, transaction management and sorting using the object programming, please refer to Dynamic Object programming and Application Development With Component-Based Object Extender.

OOP, AOP and OP

As everybody knows, OOP stands for object-oriented programming while AOP stands for aspect-oriented programming. But what is OP and why put it together with OOP and AOP? In short, OP stands for object programming. Let me give some brief descriptions for each of them first.

OOP

Object-oriented programming (OOP) is a programming paradigm using “classes” – data structures consisting of data fields and methods together with their interactions – to design applications and computer programs. It excels when it comes to breaking a system down into business components and describing business processes through them. Over the software development life cycle (SDLC), it follows a set of design principles and uses inheritance, composition and design patterns to evolve a software system. The primary efforts are design of classes based on business requirements while abiding the principles and applying the design patterns properly.

Design patterns are often employed to solve common problems in software design for a complicate system. On the other hand, the application of design patterns makes the system more complicate. The other weakness of OOP is its inability to address cross-cutting concerns.

AOP

Aspect-oriented programming (AOP) is a programming paradigm which aims to increase modularity by allowing the separation of cross-cutting concerns. It tries to address the weakness of the OOP for cross-cutting concerns. However, the AOP is still immature and not widely adopted. It is still lack of principles or patterns to follow for addressing cross-cutting concerns of a software system.

Today, most AOP tools separate cross-cutting concerns into modules and then injet or weave the modules into classes. It is ironical that in OOP we try everything possible to decouple software entities into components so that we can have a loosely-coupled and therefore more flexible system, then, in AOP we modify the components with the code of cross-cutting concerns and end up with a tightly-coupled and inflexible system. This is less elegant. And the more serious issue is the inflexibility. Once a cross-cutting code is injeted in a component, there is no easy way to turn it off. More discussions about this can be found in the article Aspects to Object vs. Aspects to Class

OP

Object programming (OP) is a programming paradigm which aims to improve software development life cycle by extending objects at runtime instead of extending classes at design time. It complements object-oriented programming by avoiding changing or creating classes, and therefore, improves the flexiblity of a software system and reduces the system maintenance cost.

With object programming, a set of behaviors are defined as methods based on business and system requirements. These behaviors are, then, attached to object’s methods as needed in an application. At runtime, the attached behaviors are performed before and/or after the invocation of the object’s methods.

Object programming does not distinguish between business concerns and cross-cutting concerns. To it, all concerns are methods. A method corresponding to a cross-cutting concern may be applied to objects, either of same type or of different types, at different places, while a method corresponding to a business concern is more likely to be applied to objects of a particular type at a specific place.

Object programming does not alter components in any way. Instead, it alters the client of components by attaching behaviors to objects of components right before they are consumed.

Object programming is flexible in a way that methods can be attached to objects as needed, which means you can use an object as is or add extra behaviors to it.

Object Programming with CBO Extender

Component-Based Object Extender (CBO Extender), as an object extensibility framework in .NET, is particularly suitable for object programming. With CBO Extender, you define a set of aspect methods to represent behaviors based on your business or system requirements. Then, you can attach the methods to objects as needed in your application. CBO Extender uses programming to interface, therefore, can only be used to add extra functionality to interface methods.

Let’s write a Hello World! application using CBO Extender. Say, you have a DoAnything class that implements an IDoAnything interface. The application code is listed as follows.

namespace HelloWorld
{
    public interface IDoAnything
    {
        void DoThing();
    }

    public class DoAnything : IDoAnything
    {
        public void DoThing()
        {
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            IDoAnything doAThing = new DoAnything();

            doAThing.DoThing();
        }
    }
}

Of course, the DoThing method of doAThing object does nothing. Now, let’s define a SayHello method and a SayBye method, and use ObjectProxyFactory.CreateProxy2 method of CBO Extender to add them to the doAThing object as extra behaviors. The application is listed as follows.

using CBOExtender;

namespace HelloWorld
{
    public interface IDoAnything
    {
        void DoThing();
    }

    public class DoAnything : IDoAnything
    {
        public void DoThing()
        {
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            IDoAnything doAThing = new DoAnything();

            doAThing = ObjectProxyFactory.CreateProxy2<IDoAnything>(
                doAThing,
                new string[] { "DoThing" },
                new Decoration2(SayHello, null),
                new Decoration2(SayBye, null)
            );

            doAThing.DoThing();
        }

        public static void SayHello(AspectContext2 ctx, dynamic parameters)
        {
            System.Console.WriteLine("Hello World!");
        }

        public static void SayBye(AspectContext2 ctx, dynamic parameters)
        {
            System.Console.WriteLine("Bye!");
        }
    }
}

Now, the DoThing method of doAThing object outputs the “Hello World!” and “Bye!”.

Actually, there is nothing that can stop you to put any logic into the SayHello method or SayBye method. Your DoAnything component indeed can do anything! To see how the CBO Extender is used to add functionality like logging, security checking, transaction management and sorting, etc, please check with the articles Dynamic Object Programming and Application Development With Component-Based Object Extender.

OOP, OP and SDLC

Can you build a real world business system from the DoAnything component using object programming? Maybe. But it may need a set of new principles and some disciplines to follow so that your system is understandable and maintainable.

In the software development life cycle (SDLC), the OOP can be used to break a system down into business components and simulate business processes through them. It should be very clear that business components should only implement business logic and avoid change once released. Then, OP can be employed to address cross-cutting concerns and alter the system as needed. OOP + OP produces a less complicate, loosely-coupled and flexible software system.

Component-Based Object Extender

Download: CBO Extender

What Is CBO Extender

Component-Based Object Extender (CBO Extender) is an object extensibility framework. As indicated by the name, it is component-based, which means it works with interfaces, and it extends objects directly instead of extending their types. CBO Extender can be used to extend any interface methods including interfaces from third party, from .NET Framework or interfaces defined by you. It is a general-purpose tool for adding functionality to objects by attaching behaviors to interface methods of the objects.

Extending Objects vs. Extending Types

Extending types involves design time efforts and is an intermediate step. The purpose is for objects of the extended types to have the additional functionality. What about extending objects directly without involving the intermediate step? That is the basic idea behind the CBO Extender.

Presuming it is simple enough and powerful enough (simple means it is easy to get it right, powerful means it can be used for most serious programming tasks), extending objects has following benefits:

  • Components are stable;
  • Extension is done on the client side of components as needed;
  • leaner application;
  • little maintenance.

What CBO Extender Does and Doesn’t

CBO Extender does

  • work directly on objects;
  • extend only interface methods and any interface methods;
  • decorate existing methods;
  • use methods as behaviors.

CBO Extender doesn’t

  • create, change or derive from components;
  • extend non-interface methods;
  • inject existing methods;
  • use classes as behaviors.

What CBO Extender Consists of

CBO Extender consists of a Dynamic Decorator and an AOP Container.

Dynamic Decorator evolved from the Decorator Pattern. It solves the same problem as the Decorator Pattern does: add additional functionality to an existing object dynamically. However, Dynamic Decorator takes a complete different route. Instead of creating decoration classes, it uses a customized .NET proxy technology to intercept method calls and applies additional functionality along the way, either before or after the execution of the target methods. One advantage of the Dynamic Decorator is that it doesn’t need to design/maintain decoration classes. And it is easy to use and can be applied to any object of any components. The article Dynamic Decorator Pattern explains Dynamic Decorator in details. The article Add Aspects to Objects Using Dynamic Decorator discusses the important features of the Dynamic Decorator.

AOP Container integrates the Dynamic Decorator with IoC (Inversion of Control) Containers. It enables any IoC container to have AOP capabilities by configuration or using code. The article AOP Container discusses adding AOP capabilities to IoC Containers by configuration. The article AOP Container 2 discusses adding AOP capabilities to IoC Containers using code.

Aspects in CBO Extender

In most AOP tools, aspects represent cross-cutting concerns and usually take form of some special classes. In CBO Extender, aspects are methods with specific signature. Although the methods may address cross-cutting concerns like logging, security checking, auditing, etc., they can also address concerns like sorting and grouping, which are specific to some types and are not cross-cutting. In the context of CBO Extender, aspects are methods that can implement any logic including cross-cutting concerns.

Use CBO Extender

You can use the Dynamic Decorator directly in your code by calling its CreateProxy<T> method. There are a number of articles describing its use, for example, Dynamic Decorator, Unity and Castle DynamicProxy Comparison.

If you use some IoC Container, you may use AOP Container to integrate CBO Extender with your IoC Container. There are two ways to use AOP Container with an IoC Container: by configuation or using code. The article AOP Container discusses how to use AOP Container by configuration with MEF, Unity and Windsor. The article AOP Container 2 discusses how to use AOP Container using code with Unity and Windsor.

CBO Extender and Application Development

CBO Extender complements component-based development by making it easy to attach behaviors to objects of a component at runtime. Here is the guideline for application development using CBO Extender:

  • Design components to meet business requirements in a general way
  • Design cross-cutting concerns as general aspects methods in shared modules
  • Design other concerns as specific aspect methods in form of local or anonymous methods
  • Extend objects as needed

The following articles discuss how the above guideline are applied to various application types.

CBO Extender vs. Other Proxy Technologies

CBO Extender uses a customized proxy that is based on .NET proxy technology. There are other customized proxies like Castle DynamicProxy and Unity Interceptor.

CBO Extender differentiates itself from other proxy technologies by its aspect. In CBO Extender, an aspect (behavior) is a method with a specific signature (a.k.a. aspect method). In other proxy technologies (Windsor or Unity), an aspect (behavior) is a class implementing a specific interface (a.k.a. behavior class).

Aspect method is conceptually simpler than behavior class. After all, why you need a class if a method can solve the problem? Aspect method also has capabilities to access target and call context. The article Dynamic Decorator, Unity and Castle DynamicProxy Comparison gives more details about their differences in terms of performance and features.

CBO Extender vs. PostSharp

PostSharp injects code into a method while CBO Extender decorates a method. PostSharp adds behaviors to classes at design time while CBO Extender adds behaviors to objects at runtime.

Though PostSharp can do almost anything within a class, it can hardly do things right. Most of time, it is simply too early to decide whether an aspect is needed for a class when you design the class. The article Aspects to Object vs. Aspects to Class discusses some issues related to design aspects for classes.

I did find a case that PostSharp can be used to implement INotifyPropertyChanged interface for a WPF application (see the article
Configurable Aspects for WPF Application Using AOP Unity Container). But in general, addressing aspects at class level is not a best practice.

Why CBO Extender

  • CBO Extender embraces component-based development;
  • Components are separated from aspects at design time and are kept separated at runtime;
  • Aspects are wired to component’s objects at runtime as needed;
  • Aspects can be powerful by chaining them and by accessing target and call context;
  • CBO Extender is simple and lightweight.

Aspects to Object vs Aspects to Class

It is clear that aspects address system (non-functional) requirements while classes address business (functional) requirements. System requirements are runtime requirements when software executes and are best addressed at object level .

Unfortunately, for all these years most of the AOP products/tools try to address aspects at class level at its design time. That may explain why AOP is still not widely adopted. In my opinion, classes should only concern about business requirements. They should not concern about system requirements. System requirements should be addressed at object level when you use the objects of the classes.

Here is why. A class is only a template for a set of objects. When you design a class, often you do not know (or may never know) every situation in which its objects are used. Take the logging (a system requirement, BTW) as an example. If you add the entering/exiting logging aspects to a class method, every object created from the class will pump entering/exiting logs when executing the method. If your code just loop through a few employees, it is probably ok. If you have hundreds of thousands of employees, do you really want to log every entering/exiting in the loop? You just can’t anticipate the situations like this.

My point here is: it is too early to decide whether you need an aspect to your class when you design the class. Then, when is the right time to consider an aspect? The answer is when you use objects of the class. By the time you use an object of the class in your code, you know the exact situation in which the object is used. Then, you can decide whether an aspect is needed for the object. If yes, the Dynamic Decorator (or maybe other tools) can be used to attach aspects to the object at the spot.

Using the Dynamic Decorator, business requirements and system requirements can be addressed separately. You use OOP to design classes to satisfy the business requirements. Then, you use the Dynamic Decorator to attach aspects to objects as needed based on the system’s runtime requirements.

I agree that Dino Esposito’s comment in his article Aspect-Oriented Programming, Interception and Unity 2.0 while he describes the benefits of AOP: the main reason for such a limited adoption (of AOP) is essentially the lack of proper tools. More specifically, I would like to say that although there exist a number of AOP tools, it is still lack of tools to address aspects at right time and at right place.

The Dynamic Decorator may be one of first serious tools to address aspects at object level. I foresee more tools will come to address aspects at object level in the near future for two reasons. First, the needs are there. Second, people may shift their focus onto solving the AOP problem at object level once they realize that aspects belong to objects at runtime not classes at design time.

More information on aspects to object can be found in the article Add Aspects to Object Using Dynamic Decorator.

Dynamic Decorator and Castle DynamicProxy Comparison

Introduction

Recently, I got chance to play Castle DynamicProxy a bit and did some comparisons between it and Dynamic Decorator. I found some interesting points and would like to share in this blog.

They are similar in that both use proxy concept. Both can be used to extend object functionality and add aspects to objects without modifying existing classes. The difference is that Dynamic Decorator overrides .NET’s RealProxy and reuses its transparent proxy technology while Castle DynamicProxy uses a customized proxy technology. Your can find more information about them in the following links: DynamicProxy::CastleProject, Dynamic Decorator Pattern and Add Aspects to Object Using Dynamic Decorator.

The CreateProxy method of the ObjectProxyFactory class in the Dynamic Decorator is mostly close to CreateInterfaceProxyWithTarget method of the ProxyGenerator class in the Castle DynamicProxy. The test is limited to use them to add some preprocessing functionality to an existing object.

Test Code

In this test, we try to add some logging functionality to an existing object. The following is the code for this test.

public class LoggingInterceptor : IInterceptor
{
    public void Intercept(IInvocation invocation)
    {
        Console.Write("Calling: " + invocation.Method.Name + "\n");
        invocation.Proceed();
    }
}

class Program
{
    static void Main(string[] args)
    {
        string path = Path.GetDirectoryName(System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName);
        FileStream fileStream = null;
        if (!File.Exists(path + "\\hrlog.txt"))
        {
            fileStream = new FileStream(path + "\\hrlog.txt", FileMode.Create);
        }
        else
            fileStream = new FileStream(path + "\\hrlog.txt", FileMode.Truncate);

        TextWriter tmp = Console.Out;
        StreamWriter sw1 = new StreamWriter(fileStream);
        Console.SetOut(sw1);

        IEmployee emp = new Employee(1, "John", "Smith", new DateTime(1990, 4, 1), 1);
        IEmployee iemp = null;
        System.Int32? id = null;
        System.String detail = "";
        DateTime? dtStart = null;
        TimeSpan? ts = null;

        //Performance test for Castle DynamicProxy
        dtStart = DateTime.Now;
        for (int i = 0; i < 1000; i++)
        {
            ProxyGenerator generator = new ProxyGenerator();
            iemp = generator.CreateInterfaceProxyWithTarget<IEmployee>(emp, new LoggingInterceptor());

            id = iemp.EmployeeID;
            detail = iemp.DetailsByLevel(2);
        }
        ts = DateTime.Now - dtStart.Value;
        Console.Write("Using Castle CreateInterfaceProxyWithTarget: " + ts.Value.ToString() + "\n");

        //Performance test for Dynamic Decorator
        dtStart = DateTime.Now;
        for (int i = 0; i < 1000; i++)
        {
            iemp = (IEmployee)ObjectProxyFactory.CreateProxy(
                emp,
                new String[] { "DetailsByLevel" },
                new Decoration((x, y) =>
                {
                    Console.Write("Calling: " + x.CallCtx.MethodName + "\n");
                }, null),
                null);

            id = iemp.DepartmentID;
            detail = iemp.DetailsByLevel(2);
        }
        ts = DateTime.Now - dtStart.Value;
        Console.Write("Using Dynamic Decorator: " + ts.Value.ToString() + "\n");

        //More features for Dynamic Decorator
        emp = (IEmployee)ObjectProxyFactory.CreateProxy(
            emp,
            new String[] { "DetailsByLevel" },
            new Decoration((x, y) =>
            {
                IMethodCallMessage method = x.CallCtx;
                string str = "Entering " + x.Target.GetType().ToString() + "." + method.MethodName +
                    "(";
                int i = 0;
                foreach (object o in method.Args)
                {
                    if (i > 0)
                        str = str + ", ";
                    str = str + o.ToString();
                }
                str = str + ")";

                Console.WriteLine(str);
                Console.Out.Flush();
            }, null),
            null);

        id = emp.DepartmentID;
        detail = emp.DetailsByLevel(2);

        Console.SetOut(tmp);
        sw1.Close();
        fileStream.Close();
    }
}

Performance

The first part of the code compares Castle DynamicProxy’s performance with Dynamic Decorator’s. In the above code, an object emp of class Employee is created. The first loop simply calls CreateInterfaceProxyWithTarget method of the ProxyGenerator class of the Castle DynamicProxy to create a proxy, then, uses the proxy to call the methods of the object emp for 1000 times. The second loop simply calls CreateProxy method of the ObjectProxyFactory class of the Dynamic Decorator, then, uses the proxy to call the methods of the object emp for 1000 times. The execution time of each loop is presented in the following table.

Castle DynamicProxy – First Loop Dynamic Decorator – Second Loop
00:01:13.4976480 00:00:00.0781225

The Dynamic Decorator is orders of magnitude faster than the Castle DynamicProxy for doing exactly same thing. Actually, the execution time for Dynamic Decorator is negligible. The Dynamic Decorator is clearly a winner in terms of performance.

Features

The following paragraphs discuss the feature differences between Dynamic Decorator and Castle DynamicProxy.

With Castle DynamicProxy, the preprocessing functionality is added to all methods of the object. There is no easy way to specify a particular method to decorate. It is either all methods or no methods to get the additional functionality. With Dynamic Decorator, however, individual methods can be specified. For instance, in the above code, we specify only the method DetailsByLevel when calling ObjectProxyFactory.CreateProxy of the Dynamic Decorator.

With Dynamic Decorator, you can access method call context from within additional functionality. For example, in the above code, we are able to get the value of the parameter of the method DetailsByLevel. I am not aware of a way to do it in the Castle DynamicProxy.

From the above code, you see the proxy of the Dynamic Decorator can be chained. The variable emp originally references to the target object. And later, it references to the proxy of the target. You can keep doing this to create a chain of proxies each time adding some extra functionality.

There are other features of Dynamic Decorator which can be used to enhance the preprocessing and postprocessing functionality. Please see the article Add Aspects to Object Using Dynamic Decorator for details.

The Dynamic Decorator has more features which can be used to enhance the preprocessing and postprocessing code.

Conclusion

The Dynamic Decorator is specifically designed to add additional functionality to objects. It is a lightweight and feature-rich tool to extend object functionality and to add aspects to objects. On the other hand, although the Castle DynamicProxy can be used to add aspects to objects, it suffers performance issue and has limited features to enhance the aspects.