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