Events Part 2 - Asynchronously call handlers

Events

In the previous post we saw how to make use of events to extend functionality. We also saw that the execution of the handlers were blocking in nature. The execution was synchronous. There might be a real benefit if the handlers were executed asynchronously without blocking the main thread. Please note that I stressed on might. You have to choose carefully if your operations requires parallelism, because this will complicate your application and would take more resources without any benefit in return. If you foresee many handlers listening to an event, this might give you the desired throughput by offloading them to background threads. If you are making the call from a UI thread, it would also be beneficial to free up the UI thread.
Since the events are handled by delegates we can leverage asynchronous methods calls. You can find more information of calling methods asynchronously here as of this writing.

There are a few things we have to consider and be cautious while dealing with events asynchronously. Events return void by default. When you use the generic delegates (EventHandler / EventHandler<EventArgs>) they always return void. If you use custom delegates which return value with your events, it can become awkward to deal with them when they have multiple handlers attached to them. I am not saying it is not possible, just difficult. You should be able to correlate each handlers return value, if not you would end up only with the value from the last handler’s result. Then again if you require return value from your events, then you might nned to use something other than events.

The only thing the subject needs to wait for is until all the handlers complete executing. If the thread (main or foreground) from which the event handlers were invoked exits before the handlers return, which would be running on the background thread, then they would be abruptly terminated. You would also only know if there were any exceptions in any of the handlers when you call the EndInvoke of the delegate.

Asynchronous Programming Pattern (APM) is now obsolete in favour of Task-based Asynchronous Pattern (TAP) and so is Event-Based Asynchronous Pattern (EAP). Calling of Begin method, dealing with IAsynResult and calling of End was not easy to implement and for a client consuming it, the very least, cumbersome.

We can now use Task.Factory.FromAsync which makes it easy to deal with APM calls by returning a Task. One of its overloads takes the Begin/End pair and while taking any additional arguments that gets passed to these methods. If you find the overloads lacking, then you can provide one of your own wrapper using TaskCompletionSource internally similar to FromAsync.

For those projects which cannot yet take advantage of TAP, I recommend using callback method when the call completes as described in MSDN. Through this one can handle multiple handlers since the callback would provide you with a unique IAsyncResult so that you don’t need to keep track of it. It provides the most flexibility and least blocking.

Ok, heading back to implement our asynchronous event handlers, we’ll see that there are not much changes that need to be done to the synchronous implementation. We would be receiving a Task for each Add. Add method signature would now be look as below

1
public async Task AddAsync(string name, int quantity)

Notice we are returning a Task and also marked it as async. Also changed the method name to reflect this as per the conventions.
One for all, all for one. If one method is async in a chain of calls, then it is best to have all the methods up the order as async-await.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
public class ProductAsyncTask
{
public event EventHandler<ProductAsyncTaskEventArgs> Saved;

// simulate data store
private readonly IDictionary<string, ProductAsyncTask> _productRepository;

public ProductAsyncTask()
{
_productRepository = new Dictionary<string, ProductAsyncTask>();
}

public string Name { get; set; }
public int Quantity { get; set; }

public async Task AddAsync(string name, int quantity)
{
if (_productRepository.ContainsKey(name))
{
_productRepository[name].Quantity = quantity;
Console.WriteLine("Thread# {2}: {0} quantity updated to {1}",
name, quantity, Thread.CurrentThread.ManagedThreadId);
// return a completed task
await Task.CompletedTask;
return;
}
var p = new ProductAsyncTask() { Name = name, Quantity = quantity };
_productRepository.Add(name, p);
Console.WriteLine("Thread# {1}: New Product added - {0} ",
name, Thread.CurrentThread.ManagedThreadId);
// wait without blocking the thread
await OnSaved(p);
Console.WriteLine("Thread# {1}: Completed add for {0}",
name, Thread.CurrentThread.ManagedThreadId);
}

protected async virtual Task OnSaved(ProductAsyncTask p)
{
var multiDels = Saved as EventHandler<ProductAsyncTaskEventArgs>;
if (multiDels == null)
{
await Task.CompletedTask;
return;
}
// list of event subscribers
Delegate[] delList = multiDels.GetInvocationList();
Task[] tasks = new Task[delList.Length];
for (int i = 0; i < delList.Length; i++)
{
EventHandler<ProductAsyncTaskEventArgs> e =
delList[i] as EventHandler<ProductAsyncTaskEventArgs>;
Task t = Task.Factory.FromAsync(
e.BeginInvoke, e.EndInvoke, this,
new ProductAsyncTaskEventArgs(p), null);
tasks[i] = t;
}
await Task.WhenAll(tasks);
}
}

Nothing much has changed inside the AddSync method. We are now awaiting on task or returning a completed task if there is nothing to continue for.
Inside OnSaved we see a little bit more action. We are now getting a list of delegates from the MulticastDelegate and use Task.Factory.FromAsync to create a Task for async call of each delegate. If we would have created a Task using Task.Factory.StartNew or Task.Run and made an Invoke of each delegate, the final outcome would be the same. But, this would have blocked each thread on the thread pool until completion since the task would run synchronously. In FromSync, the EndInvoke call would signal the completion and the thread would not be blocked.

The client application

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
var productTask = new ProductAsyncTask();
productTask.Saved += handler1.SendMail;
productTask.Saved += handler2.DoCall;
productTask.Saved += handler3.Audit;

var t1 = productTask.AddAsync("Cadbury classic", 10);
var t2 = productTask.AddAsync("Lindt Dark 80%", 10);
var t3 = productTask.AddAsync("Mars", 10);
var t4 = productTask.AddAsync("Cadbury classic", 10);
Console.WriteLine("Doing some other work here...");
try
{
Task.WaitAll(t1, t2, t3, t4);
}
catch (AggregateException ae)
{
foreach (var e in ae.InnerExceptions)
{
Console.WriteLine(e.Message);
}
}
// unregister
productTask.Saved -= handler1.SendMail;
productTask.Saved -= handler2.DoCall;
productTask.Saved -= handler3.Audit;

I have not including any error handling, but since we have a Task returned, we can follow its exception handling pattern. You can have a continuation task on fault or catch the exceptions closest to its source. Also if the subject is long lived, remember to un-register the handlers.

So we have seen how we can relatively easily make our event handlers run asynchronously using TAP.

Events Part 1 - Food for thought

Events

Event - a notification of a an occurrence or incidence, in programming terms, almost always in the past. Events are not always intuitive or easy to follow since they jump out of the natural control flow.
If we consider approaches to extend functionality without uglifying your class immediate thought goes to Dependency Injection. Whether it is a service or a Decorator, they now become the dependencies of your class, albeit through Inversion of Control. I am not saying this is bad, but raising events do not get a fair consideration.

Yet in so many cases they present as a great choice to extend functionality by reacting to them and even pass data out through to consuming clients. Yes, they can serve as a great vehicle to send data out. If you consider a method which returns void, but raises an event, then even though returning void is able to communicate or send out data through events. Neat.

Here I would be discussing on how to leverage events and improve code instead of delving into semantics of events and delegates in the DotNet framework. I intend this post to serves as a food for thought on using events to decouple behaviour.
Events enable loose coupling and promote separation of concerns. You can delegate (no pun intended) all external processing to the event handlers such as logging, notifications or calls to other services. The event could have multiple subscribers to it. It is a good way to update a subject’s dependents. As you can see, events need not be restricted to UI programming, but are also equally suitable for business components.
Let is consider a product domain. I’ll keep the domain logic simple and mundane so that we can focus on events and its usage. We wish to raise an event for each new product that gets added. The handlers(subscribers) who are interested in this event can then react to this.

Product(Subject)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
public class ProductSync
{
public event EventHandler<ProductSyncEventArgs> Saved;

// simulate data store
private readonly IDictionary<string, ProductSync> _productRepository;

public ProductSync()
{
_productRepository = new Dictionary<string, ProductSync>();
}

public string Name { get; set; }

public int Quantity { get; set; }

public void Add(string name, int quantity)
{
if (_productRepository.ContainsKey(name))
{
_productRepository[name].Quantity = quantity;
Console.WriteLine("Thread# {2}: {0} quantity updated to {1}",
name, quantity, Thread.CurrentThread.ManagedThreadId);
// no event will be raised here
return;
}
var p = new ProductSync() { Name = name, Quantity = quantity };
_productRepository.Add(name, p);
Console.WriteLine("Thread# {1}: New Product added - {0} ",
name, Thread.CurrentThread.ManagedThreadId);
OnSaved(p); // event raised
Console.WriteLine("Thread# {1}: Completed add for {0}",
name, Thread.CurrentThread.ManagedThreadId);
}

protected virtual void OnSaved(ProductSync p)
{
// check if we have any handlers listening
// and call them. Below is a short hand to do that.
(Saved as EventHandler<ProductSyncEventArgs>)?.Invoke(this, new ProductSyncEventArgs(p));
}
}

public class ProductSyncEventArgs : EventArgs
{
public ProductSyncEventArgs(ProductSync product)
{
Product = product;
}
public ProductSync Product { get; private set; }
}

I have deliberately appended Sync to the name. This is to highlight that event handlers subscribing to an event are invoked synchronously. The execution path does jump from one method to another, but the calls are blocking. I have included the thread id to show where the publishers and the subscribers are executing. This is important so that we do not have any misleading assumptions since the execution flow passes to the handlers. We also have a class ProductSyncEventArgs which inherits from EventArgs. This is a standard approach to pass arguments through events within DotNet.

Let us create a few subscribers or event handlers which need to do some work when event is raised.

Handlers (Subscribers)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
public class NotifyHandler
{
readonly ConsoleWriter cw;
public NotifyHandler()
{
cw = new ConsoleWriter();
}
public void SendMail(object source, ProductSyncEventArgs e)
{
Thread.Sleep(1000);
cw.Write("Thread# {1}: Sending email for product {0}",
ConsoleColor.Red, e.Product.Name,
Thread.CurrentThread.ManagedThreadId.ToString());
}
}

public class ExternalCallHandler
{
readonly ConsoleWriter cw;
public ExternalCallHandler()
{
cw = new ConsoleWriter();
}
public void DoCall(object source, ProductSyncEventArgs e)
{
Thread.Sleep(1000);
cw.Write("Thread# {1}: New note added for {0}",
ConsoleColor.Green, e.Product.Name,
Thread.CurrentThread.ManagedThreadId.ToString());
}
}

public class QuantityAuditHandler
{
readonly ConsoleWriter cw;
public QuantityAuditHandler()
{
cw = new ConsoleWriter();
}
public void Audit(object source, ProductSyncEventArgs e)
{
Thread.Sleep(1000);
cw.Write("Thread# {2}: Auditing for {1}. Quantity: {0}",
ConsoleColor.Yellow, e.Product.Quantity.ToString(), e.Product.Name,
Thread.CurrentThread.ManagedThreadId.ToString());
}
}

//helper to colour code console outputs
public class ConsoleWriter
{
public void Write(string message, ConsoleColor colour, params string[] args)
{
Console.ForegroundColor = colour;
Console.WriteLine(message, args);
Console.ResetColor();
}
}

The implementations are self-explanatory. I have added Thread.Sleep to simulate a load and helper class to output colour coded text to indicate some behaviour.

Application (Client)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class Program
{
static void Main(string[] args)
{
var handler1 = new NotifyHandler();
var handler2 = new ExternalCallHandler();
var handler3 = new QuantityAuditHandler();

var product = new ProductSync();
// registering handlers
product.Saved += handler1.SendMail;
product.Saved += handler2.DoCall;
product.Saved += handler3.Audit;

product.Add("Cadbury classic", 10);
product.Add("Lindt Dark 80%", 10);
product.Add("Mars", 10);
product.Add("Cadbury classic", 10);
// unregistering handlers
product.Saved -= handler1.SendMail;
product.Saved -= handler2.DoCall;
product.Saved -= handler3.Audit;
}

When you run the program you get the below output. It clearly shows the synchronous execution and how the Add call is blocked until all the handlers have not returned.
Program output

When a product is now added there can be other actions executed without having to inject external dependencies to the Product class. I would however like to point out there are a few draw backs in implementing events this way. Astute readers would have already realised that what we have seen is DotNet’s inbuilt implementation of Observer pattern and most of these drawbacks are inherit to Observer pattern.

  • Multiple subscribers and publishers make it difficult to maintain and understand code.
  • Subscriber and publishers need to know each other. This tight coupling will not allow each to vary independently.
  • The publisher holds strong references of each observer. This might create memory leaks when the subscriber does not de-register themselves.

Here I would not go into addressing each of these issues, but these could be solved using Mediator pattern or Event Aggregate pattern. Again a warning, both these patterns at first glance might seem interchangeable or have the same intent, but they are not. Mediator helps in communicating between unrelated objects, which require co-ordinations. It is not mandatory to use Event type with in Mediator. You would see behaviour inside Mediator. Event Aggregators as the name suggests deal only in maintaining subscriptions and publishing of events. Once again it need not be done using Event type. You can also manage the references of subscribers to avoid memory leaks. Of course all this would mean more work upfront.
Well, like I had mentioned, this post was supposed to be a food for thought and use of events in modelling business logic.
In a continuing post I’ll explore how we can call the event handlers asynchronously.

Do let me know your thoughts through comments on how you have used events in your business layers?

Entity Framework stumps SQL performance by defaulting to Unicode

The other day I was working on building a POC which involved a legacy database. I decided to use code first’s fluent API to map out the configuration since the database was pretty complex and I wanted to control how EF sees it.

I always have SQL profiler open when programming EF just to make sure EF is doing the right thing. With EF6 onwards you could also use context.Database.Log to review what EF does underneath.

When I ran my application, I noticed a very visible lag in performance. The table I was working on was very large, but the query was returning only one row, so the impact really stood out. But I knew that the query would not take that long to execute otherwise. I looked at the query in the profiler and at first glance it looked normal. The query was as simple as it could be. I copied it and ran it under query analyser. The query once again took perceivably longer time to finish. This told me it was not EF alone responsible. Looked at the execution plan, it did not look normal. There was an index scan instead of seek and a lot of parallelism thrown in. Then I took a closer look at the query plan and voila the reason for the slow performance became obvious.

Entity Framework defaults to Unicode. This is very easy to overlook and under certain EF strategies and configurations it can really hit your SQL performance. Note, this has nothing to do with EF itself, but how SQL server prepares and executes the query provided by EF.

Let me illustrate with an example.
Below is my sample database. Product with many sales.
Database diagram

Below is how the mapping is defined.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
public class Product
{
public int Id { get; set; }
public string Name { get; set; }
public virtual ICollection<Sale> Sales { get; set; }
}

public class Sale
{
public int Id { get; set; }
public int ProdId { get; set; }
public DateTime SaleDate { get; set; }
public virtual Product Product { get; set; }
}

public class ProductContext : DbContext
{
public ProductContext()
: base("TestDb")
{
Database.SetInitializer<ProductContext>(null);
}

public DbSet<Product> Products { get; set; }

public DbSet<Sale> Sales { get; set; }

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Product>().HasKey(p => p.Id)
.Property(p => p.Id)
.HasColumnName("ProdId")
.HasDatabaseGeneratedOption(System.ComponentModel.DataAnnotations
.Schema.DatabaseGeneratedOption.Identity);

modelBuilder.Entity<Product>()
.HasMany(s => s.Sales)
.WithOptional();

modelBuilder.Entity<Sale>().HasKey(s => s.Id)
.Property(s => s.Id)
.HasColumnName("SaleId")
.HasDatabaseGeneratedOption(System.ComponentModel.DataAnnotations
.Schema.DatabaseGeneratedOption.Identity);

modelBuilder.Entity<Sale>()
.Property(s => s.ProdId)
.HasColumnName("ProdId");

modelBuilder.Entity<Sale>()
.HasRequired(p => p.Product)
.WithMany(s => s.Sales)
.HasForeignKey(s => s.ProdId);
}
}

Below is how EF has interpreted the mapping.
EF model

Let us query for product by name.

1
var prods = prodContext.Products.Where(p => p.Name == "p3").ToList();

EF generates the below query.

1
2
3
SELECT [Extent1].[ProdId] AS [ProdId], [Extent1].[Name] AS [Name]
FROM [dbo].[Products] AS [Extent1]
WHERE N'p3' = [Extent1].[Name]

Pay attention to the Unicode conversion against the search value(N‘p3’). Below is the query plan.
Query plan

Notice how SQL is converting each row to Unicode before the search. This is what is killing your queries performance.
The fix is simple. Just let EF know that the column you are mapping to is not Unicode or is VARCHAR. This will allow EF to issue queries without the conversion.
Add mapping details for the Name property instead of mapping through convention. Specify either Not Unicode or the column type.

1
2
3
4
modelBuilder.Entity<Product>()
.Property(p => p.Name)
.IsUnicode(false);
//.HasColumnType("varchar");

If you approach using model first or code first without an existing database, you would not get into this problem since EF would create the database for you. This is also true if you reverse engineer your database to get your edmx generated. The tool would include the correct datatypes while mapping.

Now this should help me remember and hopefully help others too from stumbling.

Dependency Injection of Custom Claim Authorisation Manager

Claims

Authorisation is one of the most intertwined aspect in an application. We find it the most difficult part to isolate its implementations from rest of the logic. We can overcome partly syntactically through declarative sugar, but for more complex evaluations we might have to go inline. But the application still needs to continue checking the validity of the user.

The best thing that happened in security since .NET version 4.5 is that Claims became the base for all identity based security and with it we also saw ways through which we could externalise the authorisation logic (and also building of claims). A claim is statement or declaration made about oneself or others. When a user tries to claim access to any resource, the authorisation process assess if they trust the issuer of the claim and evaluates the claim.

In claim based authorisation the applications need not authenticate individuals and find out about the user. It is presented with claims by the user and the application just uses it to determine if they indeed have the right claim to continue. Now the application is undisturbed (decoupled) by the ever changing roles of a user or whether it has to accommodate any changed roles. As long as the user presents it with the right claims they get access.

Using claims not just simplifies authorisation, but you can use it to add other important facts about the user. During authentication, we could query multiple systems or specific sources which the application is more interested in and build the claim for the user. These could be email addresses, roles, position, mode of transport, dietary preferences anything which makes sense and need to share that information with applications. You can already see if used correctly how it would make authorisation and personalisation mush more easier in applications.

Enough with the introductions already! Windows Identity Foundation has now been merged with .NET Framework and we have access to default implementations of ClaimsAuthorizationManager. We can override this programmatically by using IdentityConfiguration or through application configuration file.

Through configuration:

1
2
3
4
5
<system.identityModel>
<identityConfiguration>
<claimsAuthorizationManager type="CustomAuthorisationManager"/>
</identityConfiguration>
</system.identityModel>

One limitation which it presents is that the custom type reference which we provide through configuration must have a 0 argument constructor. Which means we cannot specify any dependencies through the constructor.

This can however be overcome through code. We can register for the event FederationConfigurationCreated and when the FederationConfiguration is initialised, this event is raised where we can then modify the configuration to assign our own ClaimsAuthorizationManager.

Through code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
namespace ClaimsAwareApp
{
class App
{
static void Main(string[] args)
{
FederatedAuthentication.FederationConfigurationCreated +=
FederatedAuthentication_FederationConfigurationCreated;

//declarative
DoAction();

// inline
var cuthmgr = FederatedAuthentication.FederationConfiguration
.IdentityConfiguration.ClaimsAuthorizationManager;
var authContext =
new AuthorizationContext(ClaimsPrincipal.Current, "SomeResource", "Execute");
if (cuthmgr.CheckAccess(authContext))
Console.WriteLine("DoAction");
}

[ClaimsPrincipalPermission(
SecurityAction.Demand,
Operation = "Execute",
Resource = "SomeResource")]
static void DoAction()
{

}

private static void FederatedAuthentication_FederationConfigurationCreated(object sender,
FederationConfigurationCreatedEventArgs e)
{
DependencyFactory factory = new DependencyFactory();
e.FederationConfiguration.IdentityConfiguration.ClaimsAuthorizationManager =
new CustomClaimAuthorisation(factory);
//e.FederationConfiguration.IdentityConfiguration.ClaimsAuthenticationManager
// = new ClaimsAuthenticationManager();
}
}

class CustomClaimAuthorisation : ClaimsAuthorizationManager
{
private readonly DependencyFactory factory;
public CustomClaimAuthorisation(DependencyFactory factory)
{
this.factory = factory;
}

public override bool CheckAccess(AuthorizationContext context)
{
// Get instance from factory
using (var store = factory.GetStore())
{
// Do your authorisation
return base.CheckAccess(context);
}
}
}
class DependencyFactory
{
public MyStore GetStore()
{
return new MyStore();
}
}

class MyStore : IDisposable
{
public void Dispose()
{
// clean up
}
}
}

Few points to note!

You need to have system.identityModel in your configSections of your configuration file.

1
2
3
4
5
6
7
8
<configuration>
<configSections>
<section name="system.identityModel"
type="System.IdentityModel.Configuration.SystemIdentityModelSection,
System.IdentityModel, Version=4.0.0.0,
Culture=neutral, PublicKeyToken=B77A5C561934E089" />
</configSections>
</configuration>

Without the above entry you would run into the below exception.

Message=ID7027: Could not load the identity configuration because no <system.identityModel> configuration section was found.

I think this config section is mandatory to get access to instance of FederationConfiguration. I anyway have not found a work around for this.

Also note that FederationConfiguration is created as a singleton and you would always get the same instance of ClaimsAuthorizationManager or ClaimsAuthenticationManager. So take care how you manage the lifetime of the objects which you inject inside of these instances. If you need to dispose them after each call, I recommend inject Factory instance instead of the actual concrete instance. This way you can dispose of the concretes and have the factory provide you with a new instance on each call to CheckAccess in the case of authorisation.

Of course for a web application, one should register the FederationConfigurationCreated event under global.asax App start.

Practical Patterns: Refactoring with Decorator Design Pattern

This post is the second in the series of Design Patterns. You may refer to the earlier article here Practical Patterns: Refactoring with Bridge Design Pattern

One cannot always start by applying design patterns with a new or greenfield project. Majority of the times we are working on existing or brownfield projects. We should be able to identify how the requirement can be retrofit into an existing code while retaining/enhancing maintainability and not adding any technical debts.
Earlier we had observed how through Bridge design pattern we were able to structurally separate the classes so they could be extended independently. Bridge pattern is applied at the class level.
Decorator design pattern is applied to an object and not to a class. Once again this is done through composition rather than inheritance.

Let us continue with the code from the previous article in seeing how we can manage new requirements through Decorator pattern.
We’ll naturally come across a few new requirements which I am going to conjure up. Firstly, the business requires each transaction to get audited. They also require notification to be sent for certain transactions. If we look at the requirements, we need to add behaviour to the existing implementations. They need to happen when a transaction is taking place.

Any class which needs to provide a transaction needs to implement ITransaction interface. This is implemented by Personal and Corporate classes. The auditing needs to be done when there is a deposit or withdrawal. We could introduce a base class which implements auditing. This class can be inherited by those who implement ITransaction. But, we would be exhausting the only inheritance allowed on these classes since the language supports only single inheritance. Even if we go ahead with this option, it would affect all the instances of the original class. What about the other requirement? How can we apply notifications to be sent from only certain instances? If and when we decide to remove notifications, how do we efficiently do it? We cannot selectively alter the behaviour of the objects during runtime through sub-classing. Also handling both the requirements in a base class would violate the Single Responsibility Principle(SRP).

Decorator pattern helps you in applying SRP while also selectively allowing us to add behaviour to objects and in any combination.
As many examples showcase, it is not always required or necessary to have an abstract class to implement decorator. But in many cases they might be convenient to have and we’ll see why. But for now we can do without one and have just the concrete decorators. All we need is to implement the interface which we wish to extend and also have a reference of the interfaces object internally. The decorators which we implement can be stacked in any order to add behaviour and repeated too.Decorator Pattern

The new changes are highlighted in blue.

AuditTransactionDecorator implements the first requirement of audting.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
class AuditTransactionDecorator : ITransaction
{
private readonly ITransaction transaction;
public AuditTransactionDecorator(ITransaction transaction)
{
this.transaction = transaction;
}

public void Deposit(decimal amount)
{
Console.WriteLine("Auditing amount BEFORE deposit transaction {0}", amount);
this.transaction.Deposit(amount);
Console.WriteLine("Auditing amount AFTER deposit transaction {0}", amount);
}

public decimal GetBalance()
{
return this.transaction.GetBalance();
}

public void Withdraw(decimal amount)
{
Console.WriteLine("Auditing amount BEFORE withdraw transaction {0}", amount);
this.transaction.Withdraw(amount);
Console.WriteLine("Auditing amount AFTER withdraw transaction {0}", amount);
}
}

NotifyTransactionDecorator implements the next requirement of notifying.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
class NotifyTransactionDecorator : ITransaction
{
private readonly ITransaction transaction;
public NotifyTransactionDecorator(ITransaction transaction)
{
this.transaction = transaction;
}

public void Deposit(decimal amount)
{
this.transaction.Deposit(amount);
}

public decimal GetBalance()
{
return this.transaction.GetBalance();
}

public void Withdraw(decimal amount)
{
this.transaction.Withdraw(amount);
if (amount > 100)
{
Console.WriteLine("NOTIFY: The amount withdrawn has exceeded $100. The amount was {0}",
amount);
}
}
}

As you may notice, we are able to implement the new requirements in isolation and not having to modify the existing code.
In our AccountBase where we are creating the instance of type ITransaction, we can now decorate them with the new objects.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
abstract class AccountBase : IAccount
{
protected ITransaction transactionImp;
public AccountBase(string name, AccountType type)
{
Name = name;
switch (type)
{
case AccountType.Personal:
transactionImp = new AuditTransactionDecorator(
new Personal(1000));
break;
case AccountType.Corporate:
transactionImp = new NotifyTransactionDecorator(
new Corporate(5000));
break;
default:
throw new NotImplementedException("Unknown account type");
}
}

public abstract void Deposit(decimal amount);
public abstract void Withdraw(decimal amount);
public abstract decimal Balance { get; }
public string Name { get; private set; }
}

In line 10 and 14 we inject the original instance into the decorators. The decorators would now call the injected instances method along with its own. We could also stack the decorators together.

1
2
3
transactionImp = new AuditTransactionDecorator(
new NotifyTransactionDecorator(
new Corporate(5000)));

So when do we need an abstract class for decorators? Let’s take a look at our requirements again. For auditing requirement, we needed to decorate only the Deposit and Withdraw methods. For GetBalance we just had to forward the call to the internal reference of the interface’s concrete instance. For the notification, we just needed to add behaviour to the Withdraw method. Each requirement had a different set of methods being decorated. If we had to create multiple decorator classes targeting same methods, then a base class would have helped since it would provide a default implementation to methods which need to only forward the calls and allow us to implement only the targeted methods. This would also serve as a document indicating that classes derived from this base are decorators.
For example:

1
2
3
4
5
6
7
8
9
10
11
12
abstract class TransactionDecoratorBase : ITransaction
{
internal ITransaction transaction;

public abstract void Deposit(decimal amount);
public abstract void Withdraw(decimal amount);

public decimal GetBalance()
{
return transaction.GetBalance();
}
}

The implementation of auditing would look like this-

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class AuditTransactionDecorator : TransactionDecoratorBase
{
public AuditTransactionDecorator(ITransaction transaction)
{
this.transaction = transaction;
}
public override void Deposit(decimal amount)
{
Console.WriteLine("Auditing amount BEFORE deposit transaction {0}", amount);
this.transaction.Deposit(amount);
Console.WriteLine("Auditing amount AFTER deposit transaction {0}", amount);
}
public override void Withdraw(decimal amount)
{
Console.WriteLine("Auditing amount BEFORE withdraw transaction {0}", amount);
this.transaction.Withdraw(amount);
Console.WriteLine("Auditing amount AFTER withdraw transaction {0}", amount);
}
}

Which takes us to the classic textbook diagram.Decorator pattern classic example