Jun
22
Filed Under (.NET, Uncategorized) by jcisneros on 22-06-2008

PostSharp is a great open-source tool that allows you to encapsulate the non-business logic in custom attributes. That’s the Aspect Oriented Programming paradigm main goal: the separation of concerns.

This tool heps you to free the business logic from the infrastructure code such as:

  • Transactions
  • Logging
  • Permissions / Security
  • Exceptions handling
  • Caching
  • Settings

Your code will be cleaner than never.

…and why do I call it a “great tool”? Because, unlike other tools that uses reflection and other techniques that reduces performance, PostSharp works at MSIL level!. It generates MSIL code to be injected in your code at compilation time, in that way it supports any .NET language and get the best performance possible.

Furthermore, this tool is really easy to learn. You can quickly get started by using the basic features, follow this simple quick start:

The following example shows a simple PostSharp aspect to trace the execution of the methods marked with that attribute:

public class SimplestTraceAttribute : OnMethodBoundaryAspect
{
public
override void OnEntry( MethodExecutionEventArgs eventArgs)
{
Trace
.TraceInformation(“Entering {0}.”, eventArgs.Method);
Trace
.Indent();
}
public
override void OnExit( MethodExecutionEventArgs eventArgs)
{
Trace
.Unindent();
Trace
.TraceInformation(“Leaving {0}.”, eventArgs.Method);
}
}

…and it works like a charm!

The evidence:

Building the project:

Inspecting the binaries:

Results:

Resources:

Enjoy it!

Jun
16
Filed Under (.NET) by jcisneros on 16-06-2008

In this post I will describe the basics of MAF to quickly introduce this framework.

The Managed Add-In Framework is an Add-In architecture built on top of the .Net Framework aimed to address the following problems:

  • Loading/Unloading
  • Sandboxing (Add-ins can be sandboxed to a particular security permission set)
  • Isolation (isolation boundary between the Host and the Add-ins)
  • Lifetime Management
  • Discovery
  • Activation
  • Backwards compatibility
  • Forwards compatibility
  • Isolation changes (moving from AppDomain to Process isolation boundaries)
  • Sharing (taking an add-in built for one application and running it in another)

A MAF solution usually have seven types of projects:

  • Host: The main application that supports extensibility and manages the add-ins.
  • Host View: Defines the functionalities that the host expects from the add-ins. The host will work against this view directly.
  • Host Side Adapter: This is the glue between the Host View and the Contract. It has adapter classes that are used to convert to and from the host views and the contracts.
  • Contract: The interfaces used to communicate between Host and Add-Ins.
  • Add-In Side Adapter: This is the glue between the Add-In View and the Contract. It has adapter classes that are used to convert to and from the Add-In views and the contracts.
  • Add-In View: Represents the Add-In view of the methods and object types used to communicate with the host.
  • Add-In: An assembly loaded by the host to extend functionalities.

For more details about contracts and adapters go to this post: PDC05 - Managed AddIn Framework (MAF)

As you can deduce from the next picture the Host only references to the Host View and the Add-In only references to the Add-In view, so, each part hast its own view of the contract. In this way, if there is a new contract, it’s just necessary create new adapters to allow forward and backward compatibility.


If you are thinking that it is too much effort to create so many projects I have good news for you, there is an Add-In for Visual Studio that generates the Add-In View, Add-In Adapter, Host View and the Host Adapter from the Contract project. You can find the add-in here: Pipeline Builder.

Creating a contract

The first step to create a extensible host is to define a Contract. To do this you have to create a project with an Interface to define the functionalities that the host will expect from the add-ins. This interface have to derive from IContract and have to be marked with the AddInContract attribute. This is an example of an Contract:
using System;
using System.AddIn.Pipeline;
using System.AddIn.Contract;

namespace Contracts
{
  [AddInContract]
  public interface IHelloMAFContract : IContract
  {
    string SayHelloMAF();
  }
}

Then you can generate the basic Adapters and Views for the Host and Add-Ins using the Pipeline Builder.

The projects in a MAF solution should follow a defined file structure, for the Contract project, a possible output directory can be: “..\output\Contracts\”. You can find more details about the directory requirements in this topic: Pipeline Development Requirements.

Creating an Add-In

To create an Add-In, you just have to create a project with a class implementing the contract from the AddInView project and marked with the AddIn attribute. The following is an example AddIn implementation:
using System;
using System.AddIn;
using Contracts.AddInViews;

namespace AddInV1
{
  [AddIn("AddInV1", Version="1.0.0.0")]
  public class AddInV1 : IHelloMAF
  {
    public string SayHelloMAF()
    {
      return “Hello MAF!!”;
    }
  }
}

This project may be generated in the directory “..\Output\AddIns\AddInName\”.

Discovering and activating the Add-Ins

To discover the available Add-Ins the host can obtain a list of tokens that represents all the available Add-Ins of a specific type in a specific location. These tokens contains the Add-Ins information such as name and version, with that information then the host can decide which Add-Ins activate.

This is a sample code snippet for discovering and activating add ins:
static void Main()
{
  // In this sample we expect the AddIns and components to
  // be installed in the current directory
  String addInRoot = Environment.CurrentDirectory;

  // Check to see if new AddIns have been installed
  AddInStore.Rebuild(addInRoot);

  // Look for Calculator AddIns in our root directory and
  // store the results
  Collection tokens =
  AddInStore.FindAddIns(typeof(Calculator), addInRoot);

  // Ask the user which AddIn they would like to use
  AddInToken calcToken = ChooseCalculator(tokens);

  // Activate the selected AddInToken in a new AppDomain set sandboxed
  // in the internet zone
  Calculator calculator = calcToken.Activate(AddInSecurityLevel.Internet);

  // Run the read-eval-print loop
  RunCalculator(calculator);
}

Further readings