Yes - I'll be at TechEd 07.

Yes - My birthday is November 5th.

No - That doesn't bother me.

Yes - You are invited!

 

Teched Birthday party

 

Let us know whether you are coming (send me an email with your name and the number of people you plan to take with you).

We'll drop you a note on what we are up to, the weekend before. Hopefully weather is good and the flyer isn't a bad approximation :-).

You might have read about the Service Factory Customization Workshop held on Microsofts campus, the end of July.

Since we know a large portion of the Service Factory community is based in Europe, Don Smith and myself are doing a second workshop in The Netherlands.

This workshop will be similar to the workshop previously held in Redmond. The emphasis is definitely on learning about all the technologies "hands on". Little slideware and lots of fun.

Also, a lot of thanks to the good people at Infosupport who allowed us to use their facilities for the workshop.

European Service Factory Customization Workshop

A 3 day workshop on Service Factury customization, 14-15-16 november, the Netherlands.

Kruisboog 42
3905 TG Veenendaal
Netherlands
Tel. +31(0)318 - 50 11 19
Fax +31(0)318 - 51 83 59

Click here to view the location in Virtual Earth

Description

Many software factories being built today use a number of different technologies, which include the Guidance Automation Extensions (GAX), the Domain Specific Language (DSL) Toolkit, Visual Studio extensibility components, and a few other additional utilities. This is definitely true for the Web Service Software Factory: Modeling Edition. Much of the feedback we’ve received about these technologies, with regard to building and modifying software factories, revolves around the difficulty of customizing them. More than 40% of all users of the Service Factory will change it in some way before using it to build Web services. Typically, this is done to specialize it for some additional requirement or customize it towards a specific customer domain (i.e. industry vertical). Requiring development teams to know these technologies at any technical depth, beyond what the factory itself provides, justifies any effort to make the customizations as easy as possible.
This 3 day workshop will walk you through the comprehensive process of adding a new model (an entity model) to the Service Factory: Modeling Edition. You will become very familiar will all aspects of the factory infrastructure: DSL models, recipe automation, model validation, cross-model references, model views, project mapping, technology extenders, code generation, and factory deployment. Because the workshop will be hosted by members of the Service Factory team and other Software Factory experts, you will also have the opportunity to ask questions, and get a glimpse into the future of the software factory platform.

Purpose

  • Transfer knowledge from factory experts to attendees about building software factories on today’s technologies with insights on how these technologies are changing in the future.
  • Transfer knowledge from the attendees to factory experts about the most important and common types of modifications necessary to build other software factories.

Prerequisites

  • This should be considered an advanced workshop. It is highly recommended you have a working knowledge of GAX and the DSL toolkit. There will be some introductory content around the technologies, but there will be a heavy focus on writing C# source code. It is recommended you have reviewed the source code of the Service Factory : Modeling edition, which can be found at www.codeplex.com/servicefactory.
  • You must bring a laptop and a VPC will be provided. If you can have Microsoft Virtual PC installed ahead of time, it will save you from having to install it after you arrive. This will prevent you from having any other system requirements on the machine.
  • If you plan on attending, please have a number of changes you would like to make to the factory in mind. One of the main reasons we’re hosting this workshop is to be sure we understand what the most common and important customizations are (so we can make it as easy as possible). We will ask you to define your scenarios at some point while you are here.

Agenda

  • DSL modeling
  • Recipe automation (GAX)
  • Model validation
  • Cross-model references
  • Model views (tool windows)
  • Implementation project mapping
  • Technology extenders
  • Code generation framework
  • Factory deployment
  • Factory futures

Cost

  • There is no registration fee for the workshop.
  • Attendees are responsible for making and paying for their own travel to and from the training facilities.
  • Attendees are responsible for their lodging accommodations during the workshop.
    The suggested accommodation is: Ibis Veenendaal http://www.ibishotel.com/ibis/fichehotel/gb/ibi/0648/fiche_hotel.shtml
  • Lunch will be provided on all 3 days.

Registering

Please follow the registration link (in dutch) to complete your registration for the event.
Alternatively you can send an email to training.nl@infosupport.com and specify the following information

· Full name

· Company name

· Email address

· Whether a vegetarian lunch is required.

Registration is based on a first come, first serve basis.

Please email either Don (don.smith@microsoft.com) or Olaf (v-olconi@microsoft.com) if you have any questions with regards to the contents of the workshop. Please email Info Support (training.nl@infosupport.com) if you have questions related to registration or facilities.

This morning I woke up to Tom's announcement on the new EntLib Contrib release. No big surprises for me personally, since we have been working on this release together for quite some while. Tom actually picked up where I left it, when I went to sleep (and Tom woke up and got to work). Hooray for redundancy across time zones!

On the project homepage you can find a list of all extensions, in this post you find 5 reasons to go and download it now!

Reason #1: You have a need to translate SQL Server error codes (2601 - Primary Key violation, 547 Foreign Key violation, etc.) to .NET Exceptions.

The SqlException Wrap Handler can do this job for you!

Reason #2: Every once in a while you are annoyed by Enterprise Libraries configuration console, since it's Type Selector doesn't work well when hosted inside Visual Studio.

We fixed this in the Lightweight Type Selector!

Reason #3: You've been having runtime exceptions or other issues when using the Validation Application Block, because you simply didn't test your validators using all possibly inputs or cultures.

You can now play around and test your validators, using the Test Command for Validation Rules!

Reason #4: You need more general purpose validation rules to go with the Validation Application Block. Such as (personal favorite) the ExternallyConfigurableObjectValidator (which allows for nested validation and configuration in a file other than web.config or app.config).

Check out these validators!

Reason #5: You need more Policy Injection Call Handlers for the Policy Injection Application Block. Allow me to introduce you to: CursorCallHandler, OneWayCallHandler, SynchronizedCallHandler, ThreadSafeCallHandler, TransactionScopeCallHandler.

(these are unfortunately not documented on the wiki yet, but browsing through the discussions page might help you get an idea on what these are all about)

oh, and reason #6 is that it contains all the previous release contained!

meanwhile even more contributors joined to project and are willing to share their extensions with every single one of us. Yay!

Grigori Melnik ( yeah, you know... Tom++ ) is planning a new Enterprise Library release for Visual Studio Orca's. Yay!

From Grigori's weblog:
We, at patterns & practices, are planning a release of Enterprise Library for Visual Studio 2008 (Orcas). It will happen at around the same time Visual Studio 2008 is out (Feb 2008 as per our
roadmap). At a minimum, you can expect the current functionality ported to Orcas.

[Update: please fill out the questionaire at: http://www.zoomerang.com/survey.zgi?p=WEB226STCU2528]

Meanwhile, the Enterprise Library Contrib continues to grow...

There is a list of functionality on the project's homepage that has been added since the the first (July 07) release besides which Francois Tanguay has been dominating our Source Code check-in list recently, adding all sorts of cool little updates.


(note to self: I'll update the homepage shortly, to include Francois' additions).

Tom and I will be packaging all of the stuff that we've collected on CodePlex over the last 2 months, in order to do a new release in the first 2 weeks of September. Yay #2!



Keep watching this space, the Contrib project, Grigori's weblog and offcourse Tom Hollanders' weblog for more updates along the way.

If you are part of the Contrib community and have questions w/ regards to the September release, feel free to contact either me or Tom over CodePlex.  

After having hosted the EntlibContrib project for a couple of months now, I believe we have come to a point at which we have reached critical mass and provide good value over Enterprise Library (we even managed to fix some issues that where logged in the Enterprise Libraries issue tracker on codeplex!).

From this point on we will try to release every couple of months, including new contributions or bug-fixes to the previously released extensions.

Unfortunately, we do not have a testing team for the contributions project. We basically count on your feedback within our issue tracker as a means of quality assurance
J .I would like to thank all the contributors that have been so kind to share their extensions to Enterprise Library in this release. Feel free to follow their good example!

This first release of Enterprise Library Contrib contains the following:

PostSharp4EntLib - Combines the benefits of the Enterprise Library Policy Injection and of compile-time weaving by removing the limitations due to the use of remoting proxies.

LogParser - Combines the benefits of the Enterprise Library Logging Application Block with the ability to deserialize from a human readable log text file all LogEntry objects back. This enables sophisticated log filter capabilities with LINQ on normal log files (.NET 2.0 and Orcas samples) with very few lines of code.

MySql for DAAB - MySql provider for the Data Access Application Block.

SqlLite for DAAB - SqlLite provider for the Data Access Application Block.

Additional PIAB Matching Rules
  
And Matching Rule: Combines 2 Matching Rules and evaluates to "true" only if both of contained Matching Rules evalute to "true".
  
Or Matching Rule: Combines 2 Matching Rules and evaluates to "true" if either one of contained Matching Rules evalutes to "true"
  
Not Matching Rule: Contains another Matching Rules and evaluates to "true" if the contained Matching Rules evalutes to "false".

Additional VAB Validators
  
Externally Configurable Object Validator: An Object Validator that allows to use configuration from a configuration file other than web.config or app.config.

Designtime Enhancements
  
Lightweigth type-picker for VAB: An alternative type-picker for the validation application block that allows you to enter a typename in a text-box (instead of using the tree-view to navigate the whole lot of types in the current appdomain).

Extended SQL Data Access Block - This data access application block extends the SQL Data Access Block provided by Enterprise Library. It provides additional overloads for the UpdateDataSet method so that a collection of rows or a table can be passed to the DataAdapter for update. These methods were developed to support updating datasets that have multiple tables and cascading hierarchies.

 

Most people should be familiar with the term “defensive programming”. It’s a way of writing code, in which the default mode is to explicitly check all assumptions you have in mind while writing logic (most of the time throwing exceptions to the caller).Though, when does this make sense?

Assume you are developing a framework, application host or plug-in to an application host. How sure are you all the assumptions you have in mind hold, once having released whatever you are working on “out in the wild”?

What if a “friendly hacker” wants to exploit some unforeseen extensibility point in your framework, making it do cool stuff beyond something you thought was possible… would that be gain or loss in value for your framework?
Think of all the mash-ups people made against google maps, flicker, whatever web 2.0 stuff is out there. Or extensions made to “application hosts” such as the Visual Studio Shell (soon to be released and positioned as a true application host!).

My default mode is different: I won’t check assumptions I have when coding, “unless …”:

- I am exposing some surface of an application to whomever (for instance a public service boundary, user input, whatever “unfriendly hackers” could exploit to do bad things).

- I am shielding from conditions that simply cannot be handled gracefully (and will throw an exception anyways). Most of which can be done through basic parameter guarding.

-Etc

When exposing a public API I’d love to have people do whatever they think makes sense.
In return, whatever I expose meets some basic assumptions, around stuff like thread-safety, security and in general its behaviour (implied through convention or somehow more explicit).
If something is not thread-safe or possibly unsecure it should not be part of the public API.

Example would be a pattern such as:
FooBar foo = bar.GetContextualSomething() as FooBar;
if (foo != null) // whatever ContextualSomething I get back, my logic only applies on a FooBar
{
foo.DoStuff();
}

I agree that having an API that works regardless of how it is called wouldn't make sense either, though the consumers of a framework know the problem they are trying to solve best. So why not give them the benefit of doubt?

A couple of weeks ago the "Enterprise Library Contrib" project was published on CodePlex (www.codeplex.com/EntLibContrib). Meanwhile a couple of cool people joined the project, with intent to share and collaborate on the extensions they've made to EntLib.

Currently, 2 extensions have already been commited to the sourcecode; the "additional matchingrules" for PIAB and MySql support for DAAB.

If there is anything you would like to share, don't hessitate to sign up! as for now I am really curious as to how this works out.

Even though the Validation Application Block supports extensive composition of validation rules (using And and Or 'operators' and the Negated property) PIAB doesnt.

PIAB Matchingrules are always composed using an "AND" operator (Namespace is 'BusinessLogic.Actions' and Tag is 'ShouldBeAudited').
Additionally, the matchingrules themselves often contain a collection of matches that should help you to do composition such as ((Namespace is 'BusinessLogic.Actions' or 'BusinessLogic.Services') and Tag is 'ShouldBeAudited').

Fair enough, that seems pretty straightforward and allows for a fair amount of composition logic.
Though I ran in a situation a Not operator was desired. (Type is 'Foo' and not Method is 'Bar'), decided to add this and, for sake of completeness add the designtime for it (and do the same for OR and AND-operators).



I ran into this when trying to automate the creation of PIAB policies (and their matchingrules). Which probably isnt a typicial usage scenario, fair enough.

Still, if you find yourself in the need of these types of MatchingRules, feel free to re-use mine (both sourcecode and a binary copy are attached).
The binaries are compiled against an unsigned version of EntLib. Please read Tom's post on compatibility issues, before sticking those in EntLib's installation directory.


The DSL Toolkit knows a concept called shape (the thing that represents an element and is drawn on the modeling surface) and allows to define these shapes in 3 basic flavors:

1.)    Geometry Shapes. Either a Rectangle, Rounded rectangle, Ellipse or Circle
2.)    Image Shapes. An imported image
3.)    Compartment Shapes. Either a Rectangle or Rounded rectangle which contains compartments.

The “Geometry shape” has some advantages over the “Image shape”, it can be scaled and its style can be configured. The Geometry shape also features a shadow and cool highlight when hovering over it.
Geometry shapes are slightly harder to customize, though.... You should draw them in code using GDI.

Now, if you want to create your own geometry shapes it might be worth your while to have a look at some of the fonts (especially wingdings or webdings) on your system.
GDI you to import the structure of these fonts and draw them on a surface (DSL model?).



The way this works is:

1.) Place a “Geometry Shape” on your Dsl designer (mine is called “AlienShape”).
2.) In the property grid, Specify that a double derived class should be generated and set the Geometry property to “Circle”.
3.) After transforming the templates you should be able to derive from a class called “AlienShapeBase” and override its ShapeGeometry property to return your own.

public partial class AlienShape : AlienShapeBase
{
public override Microsoft.VisualStudio.Modeling.Diagrams.ShapeGeometry ShapeGeometry
{
get
{
FontShapeGeometry myShape = new FontShapeGeometry();
myShape.CharCode = (char)0x85;
myShape.FontName = "Webdings";

return myShape;
}
}
}

The FontShapeGeometry class uses the specified character and font to import this in a GDI structure, then manipulate it to fit your shape.
The implementation below, stretches the character to a Rectangularal shape. Since we derive from RectangleShapeGeomtery all the hit-testing, grabhandles, zooming and scaling should already be taken care of.

public class FontShapeGeometry : RectangleShapeGeometry
{
char c;
public char CharCode
{
get { return c; }
set { c = value; }
}

string fontName;
public string FontName
{
get { return fontName; }
set { fontName = value; }
}

public override System.Drawing.Drawing2D.GraphicsPath GetPath(IGeometryHost geometryHost)
{
RectangleF targetRect = RectangleD.ToRectangleF(geometryHost.GeometryBoundingBox);

GraphicsPath path = base.UninitializedPath;
path.Reset();

//draw the character in the GrpahicsPath on 1.1
path.AddString(new String(c, 1), new FontFamily(FontName), 1, 1, new RectangleF(0, 0, targetRect.Width, targetRect.Height), StringFormat.GenericDefault);

//Calculate the bounds of the drawn character, calculate whether we should scale it.
RectangleF currentBounds = path.GetBounds();
float scaleX = targetRect.Width / currentBounds.Width;
float scaleY = targetRect.Height / currentBounds.Height;

//Scale it
Matrix scaleTransform = new Matrix();
scaleTransform.Scale(scaleX, scaleY);
path.Transform(scaleTransform);

//Calculate the bounds of the scaled character, calculate the offset and apply this.
currentBounds = path.GetBounds();
Matrix translationTransform = new Matrix();
translationTransform.Translate(targetRect.Left - currentBounds.Left, targetRect.Top - currentBounds.Top);
path.Transform(translationTransform);

//return the path.
return path;
}
}



As you might already know, one of the additions to Enterprise Library version 3 is the ability to manage configuration files from within the Visual Studio IDE.

In order to have both the existing configuration tool and the integrated editor for Visual Studio use the same logic under the covers EntLib 3 also introduces a new assembly called Microsoft.Practices.EnterpriseLibrary.Configuration.Design.UI. This assembly contains the functionality that is shared between the 2 tools.

Since this Configuration.Design.UI is contained in the package, let's have a look at the effort it takes to create your own user interface that leverages the EntLibs designtime nodes :-). I have to add that this never was a scenario for EntLib 3, again we might be abusing it in ways it is unanticipated for *evil grin*.

Now, why would this be usefull? well maybe you work with a company that uses EntLib inside their own framework and want a branded version of this tooling. I could also see this work inside installers (after deploying a website or service you might want to configure the application, right?)

So, let's start out with creating a winforms project. Add a panel (1), list-view (2) and property grid (3). Then add all the buttons and branding you feel is vital to this applications success (4) :-)


Next, let's add some references to this project. First add the:
Microsoft.Practices.EnterpriseLibrary.Configuration.Design.HostAdapter,
Microsoft.Practices.EnterpriseLibrary.Configuration.Design.UI and
Microsoft.Practices.EnterpriseLibrary.Configuration.Design

This should get us started with all of the generic designtime features EntLib provides. You should also add references to the designtime of each block you'd like to configure using this version of the tool. This means adding references to the <block> and <block.configuration.design> assemblies (or manually copy these assemblies into the \bin\ directory, since we wont be coding against those).
For example, to have this tool manage Validation configuration, add:
Microsoft.Practices.EnterpriseLibrary.Validation and
Microsoft.Practices.EnterpriseLibrary.Validation.Configuration.Design

I added all the assemblies from EntLibs bin-directory as a reference, that should give you all the designtime features the other tools have as well.

Since we have the references, we can start coding!

first, lets add a field of type SingleHierarchyConfigurationUIHostAdapater to our form. And initialize it in our constructor. The initialization code will instantiate our "ConfigurationHostAdapter", add the control it exposes to our form (inside the Panel we designed) and wire a couple of events

public partial class Form1 : Form
{
SingleHierarchyConfigurationUIHostAdapater configurationConsoleAdapter;

public Form1()
{
InitializeComponent();

HostAdapaterConfiguration adapterConfig = new HostAdapaterConfiguration(AppDomain.CurrentDomain.BaseDirectory);
configurationConsoleAdapter = new SingleHierarchyConfigurationUIHostAdapater(adapterConfig);
Panel1.Controls.Add(configurationConsoleAdapter.EditorControl);
configurationConsoleAdapter.EditorControl.Dock = DockStyle.Fill;

configurationConsoleAdapter.SelectionChanged += new EventHandler<SelectionChangedEventArgs>(configurationConsoleAdapter_SelectionChanged);
configurationConsoleAdapter.TasksChanged += new EventHandler<TasksChangedEventArgs>(configurationConsoleAdapter_TasksChanged);
configurationConsoleAdapter.DocumentClosed += new EventHandler<EventArgs>(configurationConsoleAdapter_DocumentClosed);
}

Cool, now for the code we want to execute on these events (I assume most of this is self-explanetory):

void configurationConsoleAdapter_DocumentClosed(object sender, EventArgs e)
{
Close();
}

void configurationConsoleAdapter_TasksChanged(object sender, TasksChangedEventArgs e)
{
listView1.Items.Clear();
foreach (Task t in e.Tasks)
{
listView1.Items.Add(new TaskViewItem(t));
}
}

void configurationConsoleAdapter_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
propertyGrid1.SelectedObject = e.SelectedComponent;
}

private class TaskViewItem : ListViewItem
{
public TaskViewItem(Task t): base(t.Message)
{
Tag = t;
}
}


Then, last -but not least - lets write the handlers that execute whenever the toolstrip-buttons "Open", "Save" or "Validate" are clicked:

private void openButton_Click(object sender, EventArgs e)
{
using (OpenFileDialog dialog = new OpenFileDialog())
{
if (dialog.ShowDialog() == DialogResult.OK)
{
configurationConsoleAdapter.Load(dialog.FileName);
}
}
}

private void saveButton_Click(object sender, EventArgs e)
{
using (SaveFileDialog dialog = new SaveFileDialog())
{
if (dialog.ShowDialog() == DialogResult.OK)
{
configurationConsoleAdapter.Save(dialog.FileName);
}
}
MessageBox.Show("Save completed");
}

private void validateButton_Click(object sender, EventArgs e)
{
configurationConsoleAdapter.Validate();
MessageBox.Show("validate completed");
}

Et voila, the result after this 15 minute excercise:

Then, order a couple of hundred thumb-drives. copy the tool on them and distribute them to your companies consultants for that unique corporate feel your company has! :-)

Attached you can find the configuration-tool in the screenshot.


Again i am very proud to have been part of the development team.

Tom's announcement: http://blogs.msdn.com/tomholl/archive/2007/04/05/just-released-enterprise-library-3-0-april-2007.aspx

Download at MSDN: http://www.microsoft.com/downloads/details.aspx?FamilyID=62ef5f79-daf2-43af-9897-d926f03b9e60&displaylang=en

 

 

Every once in a while, when advocating AOP, people ask me whether this programming technique is useful apart from stuff like logging, security, instrumentation, etc, etc.
Usually I answer that I wouldn’t know, but i do know that especially in enterprise application development there so many quality concerns similar to the above, that AOP can be considered just that and still very much is worth the effort.

Even though I usually take the easy way out, I strongly believe that AOP concept can be applied to more than logging.

In fact, one of the AOP examples that are often used is about a drawing application.

Consider the following object-oriented code:

 
Using aspect-oriented programming, the requirement above (updating the display) can defined separately from all the other functionality this fictitious application may provide.




Why is it so hard to come up with AOP examples that are *not* about our “usual suspects”?

Well, mainly because most of this is hidden in the domains you work in. Finding them requires knowledge of this specific domain and proper analysis and design. The domains I am familiar with are the generic requirements developers often face when writing software (logging, caching, security, exception handling, whatnot).

Eventually most of the domains have all sorts of requirements that apply to each other and can be separated from each other; helping us to make our designs clearer and structure our code better.

Since Both Tom and Ed wrote an article explaining whatever the Policy Injection Application Block [PIAB] is, you might be interested in how to use this new block from within Enterprise Libraries February CTP. Tom, who is the Product Manager on Enterprise Library, has been keeping me fairly busy over the last couple of days and helped out posting some of the OPAB Configuration schema already.

So let’s start with this exercise in using the Policy Injection Application Block!


Since I wouldn’t know about your real world application (though feel free to post specific problems you run into on the forums!) I created my own “real world” application. An ATM (or Automated Teller Machine):

 

As most other real world application this application is about more than just decreasing the balance after a withdrawal is made. The requirements include:

  • Log all operations to a text file.
  • Log all withdrawals of $1000 or above to the eventlog (the business guys refer to these withdrawals as “Large Withdrawal”).
  • No withdrawal can be made that exceeds the customer’s credit limit
  • Exceptions that occur, should be handled gracefully

Now, let’s dive into the code and have a look at how this Policy Injection thing will help us out.
(The complete project can be found as an attachment, the complete listing of PIAB configuration can be found at the bottom of this blogpost)

Defining the “Interceptable” interface

Since we will be intercepting method calls within the application we first need to determine what methods we would be potentially interested in to intercept. This can be done in 2 ways:

1)      If we want to have the system intercept *all* calls to a specific class (and we have the freedom of defining our own base class on this class) we can do so by having this class derive from MarshalByRefObject.

2)      If we want a more fine grained interface to do interception on (or we already have a baseclass, other than MarshalByRefObject) we can have our class implement an interface, which will define the methods we can do interception on.

 

Additionally, all classes that have methods we would like to intercept need to be created using a factory, called PolicyInjection. In code this looks like:

//All methods on this class can be intercepted, it derives from MarshalByRefObject

public class InterceptAllMyMethods : MarshalByRefObject

{

    public void Method1() { }

    public void Method2() { }

}

(then, when creating an instance of the class above)

//Have the factory create the instance, this will make interception possible

InterceptAllMyMethods interceptable1 = PolicyInjection.Create<InterceptAllMyMethods>();

interceptable1.Method1(); //this method call will be intercepted by the PolicyInjection AB

or:
//Methods defined on IInterceptableMethods can be intercepted

public class InterceptMethodsInInterface : IInterceptableMethods

{

    public void Method1() { }

    public void Method2() { } //not in interface, will not be intercepted

}

 

public interface IInterceptableMethods

{

    void Method1();

}

(again, create the object using the factory)

IInterceptableMethods interceptable2 = PolicyInjection.Create<InterceptMethodsInInterface, IInterceptableMethods>();

interceptable2.Method1(); //this method call will be intercepted by the PolicyInjection AB

 

In our teller machine we choose the second option, and defined an interface that looks like the following:

public interface ITeller

{

    void WithdrawAmount20(Account account);

    void WithdrawAmount50(Account account);

    void WithdrawAmount100(Account account);

    void WithdrawAmount500(Account account);

 

    [Tag("Large Withdrawal")]

    void WithdrawAmount1000(Account account);

    [Tag("Large Withdrawal")]

    void WithdrawAmount2500(Account account);

 

    void Kicked();

}

 

When creating an instance of the Teller class (which derived from this interface) we do this using the PolcyInjection factory. This will make every method call in the interface about a possible victom for interception.

teller = PolicyInjection.Create<Teller, ITeller>();

Now this is done, we can proceed with our first requirement:

Logging every operation to a text file

Since we have our instance of the Teller class created using the PolicyInjection factory, next thing we need to think about is what to do in order to satisfy this requirement.

Every operation in this requirement can be interpreted as “all method calls to the ITeller interface” (above). Logging this to a textfile, in our context can be interpreted as use Enterprise Library logging to write the event to a text file.

These 2 bits of information (the where and the what) make up a Policy. This Policy can be configured and will be Injected into the Teller class (without the need of explicitly writing the code to call The Logging Application Block, over and over again).

The generic skeleton for a policy in configuration looks like the following:

<policies>
<add name="PolicyName">

  <matchingRules>

    [List of rules that should evelautate true,

    before policy is applied]

  </matchingRules>

  <handlers>

    [List of handlers that should be invoced

    by this Policy]

  </handlers>

</add>

</policies>

 

For this specific policy we add:

1)      A rule to the matchingRule-element that will match any method on the ITeller interface

2)      A handler that calls into the Logging Application block, to update the textfile, we use as a log.

In the applications configuration this now looks like the following:

<add name="LogAllOperationsToFile">

  <matchingRules>

    <add

      name="Type is ITeller"

      type="Microsoft.Practices.EnterpriseLibrary.PolicyInjection.MatchingRules.TypeMatchingRule, Microsoft.Practices.EnterpriseLibrary.PolicyInjection"

      ignoreCase="false"

      match="ITeller" />

  </matchingRules>

  <handlers>

    <add

      name="Log operation to text file"

 type="Microsoft.Practices.EnterpriseLibrary.PolicyInjection.CallHandlers.LogCallHandler, Microsoft.Practices.EnterpriseLibrary.PolicyInjection.CallHandlers"

      logBehavior="Before"

      beforeMessage="This is the before message"

      afterMessage="This is the after message"

      includeParameterValues="true"

      includeCallStack="true"

      includeCallTime="false"

      priority="42"

      severity="Information">

       <categories>

         <add name="OperationOnTeller" />

       </categories>

    </add>

  </handlers>

</add>

Every Handler or MatchingRule has its own set of configuration settings.

As a Rule we use the TypeMatchingRule and we configure it to match the ITeller type.

As a handler we use the LogCallHandler and do this in a verbose way (it will log incoming parameter values, as well as the current callstack). The category OperationOnTeller will be passed to the Logging Application Block, together with the information about the specific call. This category is configured to log to a textfile.

Believe it or not (and if you don’t, the application attached will prove it) but from this point on all calls to the ITeller interface will be logged to a textfile (trace.log, in the applications run directory).

Next up is Requirement #2:

Large transactions should be logged to the eventlog

You might well have noticed that the methods on the ITeller interface for a Transfer of $1000 and $2500 have an attribute on them.

    [Tag("Large Withdrawal")]

    void WithdrawAmount1000(IPrincipal authenticatedUser);

    [Tag("Large Withdrawal")]

    void WithdrawAmount2500(IPrincipal authenticatedUser);


PIAB allows us to configure a MatchingRule (similar to the one we specified to match all operations on the ITeller interface) based on these tag-values. This comes in handy with this second requirement, since it allows us to explicitly annotate the methods we are interested in.

Similar to the implementation of our first requirement, we set up a Policy in configuration that will call the Logging application block to do work when a method is called. This time around we specify a TagAttributeMatchingRule in the matchingRules element. Have a look at its definition in config:

<add name="LogLargeWithdrawalsToEventLog">

  <matchingRules>

    <add name="Tag is Large Withdrawal" type="Microsoft.Practices.EnterpriseLibrary.PolicyInjection.MatchingRules.TagAttributeMatchingRule, Microsoft.Practices.EnterpriseLibrary.PolicyInjection, Version=2.9.9.2" ignoreCase="false" match="Large Withdrawal" />

  </matchingRules>

  <handlers>

    <add name="Log operation to text file" type="Microsoft.Practices.EnterpriseLibrary.PolicyInjection.CallHandlers.LogCallHandler, Microsoft.Practices.EnterpriseLibrary.PolicyInjection.CallHandlers, Version=2.9.9.2" logBehavior="Before" beforeMessage="Large withdrawal has been made" includeParameterValues="true" severity="Information">

      <categories>

        <add name="LargeWithdrawal" />

      </categories>

    </add>

  </handlers>

</add>

Again the category “LargeWithdrawal” is configured inside the logging application to write messages to the eventlog.

(I left out some of the optional configuration settings on the logging-handler, the previous snippet contains a more complete list of possibilities)

Enough of Logging? Next up is Validation

No withdrawal can be made that exceeds the customer’s credit limit

Since the February CTP only supports validation incoming parameter instances as a whole (support to validate a parameter using attributes put on the parameter declaration will be added in the final release) we need to find a good place to inject this validation behavior.

In our sample application there is a class called Account, which has a method WithdrawFunds:


public class Account : MarshalByRefObject

{

    public void WithdrawFunds(Withdrawal withdrawal)

    {

        AccountData accountData = AccountRepository.RetrieveAccount(customerName);

        accountData.Balance -= withdrawal.Amount;

        accountData.TransactionHistory.Add(new TransactionHistoryData(withdrawal.Amount, DateTime.Now));

    }

 

The Withdrawal class is annotated with attributes to do validation on whether the Withdrawal doesn’t exceed the customer’s credit limit. So we decide to intercept this method and validate its parameter, again using PIAB configuration.

Also note that this class derives from MarshalByRefObject and we don’t need to define an interface to do interception. When creating an instance of Account, we simply call the Factory, passing it the constructor arguments:

account = PolicyInjection.Create<Account>(Environment.UserName);

In configuration there is no need to apply this policy on all methods declared on Account, only intercepting the WithdrawFunds method will do.

We decide to do this with a combination of MatchingRules, the NamespaceMatchingRule, TypeMatchingRule and MemberNameMatchingRule can be combined to match our WithdrawFunds- method (without matching other methods, called ‘WithdrawFunds’).

Combining MatchingRules can be done by adding all of them inside the matchingRule element together. These combined MatchingRules are all evaluated and only methods that match all of them are intercepted.

As the Handler for this Policy we configure the ValidationCallHandler, which will validate all parameters passed to the intercepted method. We configure this instance of the ValidationCallHandler to use the default RuleSet (this is done by leaving the ruleSet attribute empty) and set the specificationSource-attribute to Attributes, since the validation logic on our Withdrawal class is implemented using attributes (other flavors we’ve got are: Configuration or Both).

<add name="ValidateWithdrawalsOnTeller">

  <matchingRules>

    <add name="Namespace is AutomatedTeller.Logic" type="Microsoft.Practices.EnterpriseLibrary.PolicyInjection.MatchingRules.NamespaceMatchingRule, Microsoft.Practices.EnterpriseLibrary.PolicyInjection, Version=2.9.9.2" ignoreCase="false" match="AutomatedTeller.Logic" />

    <add name="Type is Account" type="Microsoft.Practices.EnterpriseLibrary.PolicyInjection.MatchingRules.TypeMatchingRule, Microsoft.Practices.EnterpriseLibrary.PolicyInjection, Version=2.9.9.2" ignoreCase="false" match="Account" />

    <add name="Member is WithdrawFunds" type="Microsoft.Practices.EnterpriseLibrary.PolicyInjection.MatchingRules.MemberNameMatchingRule, Microsoft.Practices.EnterpriseLibrary.PolicyInjection, Version=2.9.9.2" ignoreCase="false" match="WithdrawFunds" />

  </matchingRules>

  <handlers>

    <add name="Validate Parameters" type="Microsoft.Practices.EnterpriseLibrary.PolicyInjection.CallHandlers.ValidationCallHandler, Microsoft.Practices.EnterpriseLibrary.PolicyInjection.CallHandlers" ruleSet="" specificationSource="Attributes" />

  </handlers>

</add>

Having all of this set up properly, the ValidationCallHandler throws an exception of the ArgumentValidationException when the input to our method is invalid. This leads us to implementing our last requirement:

Exceptions that occur, should be handled gracefully

When customers hit their credit limit, they occasionally become aggressive and start kicking the machine. Now -don’t start slapping your computer around! –there is a “Kick machine” button on the applications UI which can be used to simulate this.

Both the “Kick machine” button and validation-failure of a withdrawal (when exceeding credit limit) causes an exception to be thrown. We already have the Exception Handling block and configuration in place to deal with these exceptions, though we want to use the PIAB to call into the Exception Handling block.

In our example the Exception Handling Block is used to translate these unfortunate events into Exceptions with messages proper to show in the UI. Since all calls into our business logic flow through the ITeller interface, we decide that would be the place to intercept calls and when intercepting we have the ExceptionCallHandler call into the Exception Handling Block.

Again, in our policy-configuration we match to a combination of MatchingRules (to be more concise in where we would like to intercept): Namespace is AutomatedTeller.Logic and Type is ITeller.

The ExceptionCallHandler is configured to call into the Exception Handling block, using the Exception-policy UI Policy.

The final piece of PIAB Configuration we add to our app.config then looks like the following:

<add name="TranslateExceptionsForUI">

  <matchingRules>

    <add name="Namespace is AutomatedTeller.Logic" type="Microsoft.Practices.EnterpriseLibrary.PolicyInjection.MatchingRules.NamespaceMatchingRule, Microsoft.Practices.EnterpriseLibrary.PolicyInjection, Version=2.9.9.2" ignoreCase="false" match="AutomatedTeller.Logic" />

    <add name="Type is ITeller" type="Microsoft.Practices.EnterpriseLibrary.PolicyInjection.MatchingRules.TypeMatchingRule, Microsoft.Practices.EnterpriseLibrary.PolicyInjection, Version=2.9.9.2" ignoreCase="false" match="ITeller" />

  </matchingRules>

  <handlers>

    <add name="UI ExceptionHandler Policy"

         type="Microsoft.Practices.EnterpriseLibrary.PolicyInjection.CallHandlers.ExceptionCallHandler, Microsoft.Practices.EnterpriseLibrary.PolicyInjection.CallHandlers" exceptionPolicyName="UI Policy"/>

  </handlers>

</add>

Since our application now complies with the requirements defined for it to run, I’d suggest we send the whole lot to test. Our job here seems done; we implemented the requirement for this application using configuration and the Policy Injection Block.

Additional information

The Policy Injection Application Block is still not finished, nor is the public interface (or configuration) fixed. These could well change before we release the final version. Also there are some known issues with this release of PIAB; still it should give you a fair idea of how this is envisioned to work.

The list of MatchingRules you can with in this CTP is:

  • AssemblyMathingRule  (matches methods in a specific assembly)
  • CustomAttributeMatchingRule (matches methods with an arbitrary attribute)
  • MemberNameMatchingRule (matches a method by its name)
  • MethodSignatureMatchingRule (matches a particular overload of a method)
  • NamespaceMatchingRule (matches methods in a specific namespace)
  • ReturnTypeMatchingRule (matches methods with a specific return  type)
  • TagAttributeMatchingRule (matches methods with the TagAttribute and a specific tag-value)
  • TypeMatchingRule (matches methods on a specific type)

The list of Handlers in this CTP is (we should be familiar with these now):

  •  LogCallHandler
  •  ValidationCallHandler
  •  ExceptionHandlingCallhandler

There are stubs for the following Handlers (which won’t work, but it seems a fair assumption that these will be included in the final releaseJ):

  • PerformanceCounterCallHandler
    Increments performance counters when a method is intercepted
  • CachingCallHandler
    Caches the output of a method and short circuits the calls if the return value was cached previously
  • AuthorizationCallHandler
    Calls a configured authorization provider and does an access-check before the method is being executed, either throwing a UnAuthorizedException or proceeding with the invocation

The PIAB handlers are executed in the order at which they appear in configuration. This allows you to control, which is done first: caching or authorization.
Caching the authorization logic does not make a lot of sense, does it? ;-)

For ObjectBuilder users there is an additional method of creating an interceptable proxy (and using this application block in their own frameworks). This can be done using the PolicyInjectionStrategy and PolicyInjectionPolicy. If you’re an OB-geek (such as myself) you probably know what to do with those.

Good luck having your own way with this new block. For questions, comments and bugs you run into you can use the communities’ forum at: www.codeplex.com/entlib

 

The complete PIAB configuration we used in this sample is as follows:


<?xml version="1.0" encoding="utf-8"?>

<configuration>

  <configSections>

    <section name="policyInjection" type="Microsoft.Practices.EnterpriseLibrary.PolicyInjection.Configuration.PolicyInjectionSettings, Microsoft.Practices.EnterpriseLibrary.PolicyInjection, Version=2.9.9.2" />

  </configSections>

  <policyInjection>

    <policies>

      <add name="LogAllOperationsToFile">

        <matchingRules>

          <add name="Type is ITeller" type="Microsoft.Practices.EnterpriseLibrary.PolicyInjection.MatchingRules.TypeMatchingRule, Microsoft.Practices.EnterpriseLibrary.PolicyInjection, Version=2.9.9.2" ignoreCase="false" match="ITeller" />

        </matchingRules>

        <handlers>

          <add name="Log operation to text file" type="Microsoft.Practices.EnterpriseLibrary.PolicyInjection.CallHandlers.LogCallHandler, Microsoft.Practices.EnterpriseLibrary.PolicyInjection.CallHandlers, Version=2.9.9.2" logBehavior="Before" beforeMessage="This is the before message" afterMessage="This is the after message" includeParameterValues="true" includeCallStack="true" includeCallTime="false" priority="42" severity="Information">

            <categories>

              <add name="OperationOnTeller" />

            </categories>

          </add>

        </handlers>

      </add>

      <add name="LogLargeWithdrawalsToEventLog">

        <matchingRules>

          <add name="Tag is Large Withdrawal" type="Microsoft.Practices.EnterpriseLibrary.PolicyInjection.MatchingRules.TagAttributeMatchingRule, Microsoft.Practices.EnterpriseLibrary.PolicyInjection, Version=2.9.9.2" ignoreCase="false" match="Large Withdrawal" />

        </matchingRules>

        <handlers>

          <add name="Log operation to text file" type="Microsoft.Practices.EnterpriseLibrary.PolicyInjection.CallHandlers.LogCallHandler, Microsoft.Practices.EnterpriseLibrary.PolicyInjection.CallHandlers, Version=2.9.9.2" logBehavior="Before" beforeMessage="Large withdrawal has been made" includeParameterValues="true" severity="Information">

            <categories>

              <add name="LargeWithdrawal" />

            </categories>

          </add>

        </handlers>

      </add>

      <add name="ValidateWithdrawalsOnTeller">

        <matchingRules>

          <add name="Namespace is AutomatedTeller.Logic" type="Microsoft.Practices.EnterpriseLibrary.PolicyInjection.MatchingRules.NamespaceMatchingRule, Microsoft.Practices.EnterpriseLibrary.PolicyInjection, Version=2.9.9.2" ignoreCase="false" match="AutomatedTeller.Logic" />

          <add name="Type is Account" type="Microsoft.Practices.EnterpriseLibrary.PolicyInjection.MatchingRules.TypeMatchingRule, Microsoft.Practices.EnterpriseLibrary.PolicyInjection, Version=2.9.9.2" ignoreCase="false" match="Account" />

          <add name="Member is WithdrawFunds" type="Microsoft.Practices.EnterpriseLibrary.PolicyInjection.MatchingRules.MemberNameMatchingRule, Microsoft.Practices.EnterpriseLibrary.PolicyInjection, Version=2.9.9.2" ignoreCase="false" match="WithdrawFunds" />

        </matchingRules>

        <handlers>

          <add name="Validate Parameters" type="Microsoft.Practices.EnterpriseLibrary.PolicyInjection.CallHandlers.ValidationCallHandler, Microsoft.Practices.EnterpriseLibrary.PolicyInjection.CallHandlers" ruleSet="" specificationSource="Attributes" />

        </handlers>

      </add>

      <add name="TranslateExceptionsForUI">

        <matchingRules>

          <add name="Namespace is AutomatedTeller.Logic" type="Microsoft.Practices.EnterpriseLibrary.PolicyInjection.MatchingRules.NamespaceMatchingRule, Microsoft.Practices.EnterpriseLibrary.PolicyInjection, Version=2.9.9.2" ignoreCase="false" match="AutomatedTeller.Logic" />

          <add name="Type is ITeller" type="Microsoft.Practices.EnterpriseLibrary.PolicyInjection.MatchingRules.TypeMatchingRule, Microsoft.Practices.EnterpriseLibrary.PolicyInjection, Version=2.9.9.2" ignoreCase="false" match="ITeller" />

        </matchingRules>

        <handlers>

          <add name="UI ExceptionHandler Policy"

               type="Microsoft.Practices.EnterpriseLibrary.PolicyInjection.CallHandlers.ExceptionCallHandler, Microsoft.Practices.EnterpriseLibrary.PolicyInjection.CallHandlers" exceptionPolicyName="UI Policy"/>

        </handlers>

      </add>

    </policies>

  </policyInjection>

</configuration>

 Let’s start out with a little history here.

About 1.5 year ago I worked as a development coach to a team of programmers at a large dutch insurance broker. To satisfy some of the infrastructural requirements we spec-ed in enterprise library v1. The team I worked at had a pretty sophisticated build environment set up and all sorts of procedures and protocols to propagate changes to different environments (test, production and so on). Since the project just started we were still trying to make sense of all of these processes and figuring out how we could comply with these, at best. As with most problems, the fundamentally better you would like to solve them, the more complicated they become. This at least was the case for managing and propagating changes to the configuration files within these environments. I had a fair understanding of how Enterprise Libraries configuration tool worked and how to extend it and during a month-or-so holiday at my family’s vacation house in Finland I hacked something together that would solve this particular problem. For kicks and because I felt this particular problem had bugged me for long enough.

Quickly after posting this solution on my weblog, the patterns & practices team contacted me and engaged me on a contract to work on Enterprise Library v2. Unfortunately the feature got cut and most of my time was spend on more sensible Enterprise Library v2 features. This time around (with Enterprise Library v3 on its way) the extension finally made it “above the line”.

So, what is this “environmental overrides”-thing and what value does it add to Enterprise Library?

Environmental Overrides is an extension to Enterprise Libraries configuration tooling that can help you keep track of differences in configuration throughout your infrastructure. The extension is part of the designtime and not of the runtime parts of Enterprise Library, which means that it will be compatible with any application written on top of Enterprise Library.

Managing differences between configuration files can be done in the same view you would edit configuration settings for a particular “Configuration Node”. For each environment configured in the editor you will have the possibility to either “override” the settings for a particular environment, or keep the settings for this environment in sync with the original. Configuring the environment can be done from within the configuration-treeview, adding new environment nodes underneath the “Environments” node.

Environmental Overrides in Configuration Tool
A configuration hierarchy that contains 2 environments ‘Test’ and ‘Production’ of which one has different values the LogEnabled filter.

Every environment that is configured in the tool, will maintain its own “Environment Delta File” (or .dconfig file), which is updated after saving the configuration as a whole. This Environment Delta File contains all the differences specific to that environment and some additional metadata for merging the differences into a new and complete configuration file that can be deployed. The main advantage here is that an Environment Delta File can be distributed separately of the original configuration file and managed by someone that has access to all the passwords, server-names and whatnot of the different environment.

Relationship between Original Configuration File, Environmental Delta File and Merged Environment Configuration
Relationships between Original Configuration File, Environment Delta File and Merged Configuration File.

Another new and hopefully useful addition is the ability to merge the Environmental Delta File and Original using a command line tool, which allows automating this process within for instance a build or integration server.


The Environmental Overrides extension will be included in the next CTP of Enterprise Library 3.0, available soon –in a web browser near you!
www.codeplex.com/entlib

 

 

Because of the lack postings on this weblog, below is a little heads-up on whatever I have been doing recently.

During the second half of 2006 I’ve been fairly busy implementing a “software factory” strategy (whatever that means J) for one of the bigger consultancy companies based in europe. This certainly was a very interesting (and otherwise valuable) experience. Even though I can’t share any internals on this work, I should be able to do a post or 2 on software factories in general (and whatever I think makes sense in this ballgame). Ever since “The software factories book” got published, this has been a very interesting subject for most companies doing software development.
The basic principle is to gain productivity manufacturing software, and from what I’ve seen around (some companies being more successful than others) this promise seems to hold.

At this moment I am involved in the development of Enterprise Library version 3 – As most people in the Enterprise Library community know - Tom Hollander’s blog is probably the best source for news on whatever we are doing (or plan to do) in this release. Also; the Enterprise Library community has moved to its new home at CodePlex– where you can download our first CTP of version 3 and discuss the latest bits in one of the forums.

.NET Configuration Manager development is currently on a hold – My plans to “Configure the world!” have not faded –but because of the dependency of this project on Enterprise Library 2 (of which currently a successor is being developed) and time constraints, I decided to put this project on hold. Apologies for being such a bad host to this community. Eventually I hope this is all for the better, since Enterprise Library 3 should contain new facilities for the community to do this type of development.

Aspect Oriented Programming – As some might know, I am very passionate about Aspect Oriented Programming. Even though this programming technique is rapidly gaining acceptance in the Java communities, Microsoft developers have seldom heard about AOP –or even worse: think of it as being evil. Since I actually share many of the concerns surrounding AOP, I decided to embed my own Aspect Oriented Programming environment into the Visual Studio IDE. This environment aims at having all the bells and whistles Microsoft developers are used to work with and tries to mitigate most of the concerns surrounding AOP. I currently have a fairly stable beta of this environment, that builds on top of this previous proof of concept. More on this will definitely follow!

More Posts Next page »