I just posted my latest pet-project in the downloads section of this site (look in the Free Code Projects folder). This is an extensibility framework that I wrote to provide plumbing for some of my favorite extensibility patterns. I recently recorded a DnrTv episode, showing it off, so I won’t go into it in great detail here. I offer it to anyone who wants to check it out free-of-charge. All I ask in return is that if you find it cool and/or useful, to let me know. I’m currently working on the next version which adds a couple of more patterns and I have many more things planned for it, but none at the expense of its simplicity of usage. The code download includes the framework and sample usage scenarios as shown on the show. The version I posted also covers a provider model which was not done when I recorded the show. I’ll have a full Help file soon so please bare with me. This framework is not meant to be a workflow solution, as I explained on the show. It’s also very different from MEF and provides different patterns. I have nothing against MEF, but extensibility is something I’ve been doing for a long time and I have my own patterns and my own ways of doing things. This is what the Pipeline Framework wraps. Save your breath if all you are going to comment on is that I should be using MEF instead. As I said, the patterns I use in this framework are very different. I’ll post regular updates as I add new features. In the mean time, I look forward to your comments and suggestions, positive or negative.
Callback functionality in WCF allows the service to call back to the client and send information or notification back. In essence, reversing the client-service roles. It’s a rather simple model with great benefits, specially if you want to keep the client notified on a long running process and display said notifications on the UI. However, it’s not a trivial matter to deal with proper thread handling when using this functionality. Most WCF callback demos will simply popup message boxes to show you when a callback has taken place, but if you need to do something more substantial that is UI-related, there’s a few other things you need to take into consideration. In the second installment of “This Week In Code”, I’ll give you a demonstration of a typical callback demo that you may run into often. Then I’ll change it to a more real-world scenario and introduce additional thread-handling details that you must undertake. I’m not going to turn this posting into a WCF callback tutorial so I’m going to assume that you know how callbacks work and how to set them up. Here’s some client code that calls a service: private void btnSimpleCall_Click(object sender, EventArgs e)
{
using (MyDuplexClient proxy = new MyDuplexClient(new InstanceContext(this)))
{
proxy.SimpleTest();
}
}
As you can see, it’s called from a button’s Click event. This will become important later.
And here’s the service operation that calls back to the client:
public bool SimpleTest()
{
Console.WriteLine("Serviced called. Performing callback.");
IMyCallback callback = OperationContext.Current.GetCallbackChannel<IMyCallback>();
if(callback != null)
{
callback.PerformCallback();
}
Console.WriteLine("Callback performed.");
return true;
}
The client that made the service call is a Windows Form and as I stated, it was a button that fired off the event. The form itself is the implementor of the callback contract, which is why the InstanceContext instance wraps this. Of course, the form needs the callback contract’s implementation because that’s what gets called when the service executes the callback operation. Here’s that implementation now.
public void PerformCallback()
{
MessageBox.Show("Callback from service on the client");
}
This simple example will work just fine because the callback is simply throwing up a message box. This mean it’s not accessing the actual form’s UI so there will not be any threading issues. Unfortunately, most examples you see on WCF callbacks do only this and as soon as the developer mimics this pattern but performs some UI update to the actual form, they run into problems. Let me alter my code example and explain why.
Ok, so this next example is supposed to make a service call from the form’s button, then the service will perform a potentially long iteration and every so many items in the loop, it will call back to the client to report progress. The client simply wants to use the value in the callback to update a progress bar o the form:
private void button1_Click(object sender, EventArgs e)
{
int max = Convert.ToInt32(txtMax.Text);
int step = Convert.ToInt16(txtStep.Text);
progressBar1.Minimum = 0;
progressBar1.Maximum = max;
MyDuplexClient proxy = new MyDuplexClient(new InstanceContext(this));
int[] numbers = proxy.GetNumbers(max, step);
foreach (int number in numbers)
{
lstNumbers.Items.Add(number.ToString());
}
}
public void ReportProgress(int progress)
{
progressBar1.Value = progress;
}
So what do you think is going to happen here? Well we have a potential catch-22 with this scenario. By default the callback will me automatically be marshaled to the UI thread before it gets executed on the client. If that happens, accessing the progress bar directly from the callback operation is perfectly fine, except that the UI thread is currently in the middle of a service call, since it was initiated in the button click, so we have a deadlock scenario there.
One thing I can do is decorate the form (as the implementor of callback contract) with the CallbackBehavior attribute and tell it to not use the form’s Synchronization Context:
[CallbackBehavior(UseSynchronizationContext = false)]
public partial class Form1 : Form, IMyCallback
This means that the callback will now be executed on a background thread and not the same thread as the one that made the service call initially (which is the default behavior). But now I’ve introduced another problem. The ReportProgress callback operation can no longer directly access the UI since it’s not on the UI thread, so I need to marshal up to the UI thread in order to access the progress bar.
The best way to do this is to use the form’s Synchronization Context; a feature introduced back in .NET 2.0 but still relatively unknown. Rather than use the old “invoke” technique, I’m going to grab the form’s synchronization context as early as possible and store it in a class-wide variable. It doesn’t get any earlier than the form’s constructor, so I’ll do it there:
public Form1()
{
InitializeComponent();
_SyncContext = SynchronizationContext.Current;
}
SynchronizationContext _SyncContext = null;
Now I have accessible to me at any time, a variable that represents the form’s thread execution context; and I can use this variable from any thread I want since it will always point back to the UI thread.
Next, I’ll modify the callback operation to use the _SyncContext object in order to fire code to the thread it represents, in this case the UI thread:
public void ReportProgress(int progress)
{
SendOrPostCallback setText = delegate
{
progressBar1.Value = progress;
};
_SyncContext.Post(setText, null);
}
Well, that takes care of my marshaling task, but I’ve just introduced the old problem all over again. Remember, the UI thread was in use by the button’s event which is not over yet. It seems I’m going round and round with nowhere to go. Well, I do have a way out of this. The solution to the problem lies in the way I fired off the service operation. If you recall, my goal was to fire off the operation, receive occasional callbacks, and then once the service call was complete, I want to display results to a list box. What I need to do is not lock up the UI while I make the service call so I’m going to fire off the service call on another thread; but not just the service call, the update to the list box as well. If I don’t do both, then the service call will fire on another thread and the list box will attempt to update right away. So the button’s Click event will make the service call on a separate thread, after which, on that same thread it will update the list box with the service operation results. But since that’s a UI operation, it needs to marshal that little bit up to the UI. But never fear, I have my old friend, _SynchronizationContext at my disposal.
Here’s the new button Click event:
private void button1_Click(object sender, EventArgs e)
{
int max = Convert.ToInt32(txtMax.Text);
int step = Convert.ToInt16(txtStep.Text);
progressBar1.Minimum = 0;
progressBar1.Maximum = max;
int[] numbers;
MyDuplexClient proxy = new MyDuplexClient(new InstanceContext(this));
Thread thread = new Thread(delegate()
{
numbers = proxy.GetNumbers(max, step);
SendOrPostCallback addListItem = delegate
{
foreach (int number in numbers)
lstNumbers.Items.Add(number.ToString());
};
_SyncContext.Post(addListItem, null);
});
thread.Start();
}
The only drawback with this technique is that as soon as the button is clicked, the user will have control of the UI returned. This may or may not be a good thing. As you can see, there’s a lot to be concerned about when you’re using WCF callback’s to update UI. The solution that immediately comes to mind to control the UI fully, is to use an asynchronous delegate instead of a Thread object. in fact, the Thread object is not a good idea anyway because it doesn’t use the thread pool and thread initiation carries a lot of weight. If I change the code to use an asynchronous delegate, I can declare the IAsyncResult object that the invoking the delegate will return, at a class level. Doing this, gives me access to the state of the asynchronous call anywhere on the form. Then I can check for the IsCompleted property before allowing other UI activity to occur.
Here’s the re-work using an asynchronous delegate instead. Notice that thanks to the Func delegate and its overloads, I didn’t need to create my own delegate for this. Also notice that true to the async delegate pattern, I use a callback method (not to be confused with the service callback) that will get fired after the task of the delegate is completed. And it is here where I’ll update my list box. The async delegate callback method gets fired on the same background thread that the delegate did its work, so I still need to marshal up to the UI thread in order to update it.
private void button2_Click(object sender, EventArgs e)
{
int max = Convert.ToInt32(txtMax.Text);
int step = Convert.ToInt16(txtStep.Text);
progressBar1.Minimum = 0;
progressBar1.Maximum = max;
MyDuplexClient proxy = new MyDuplexClient(new InstanceContext(this));
Func<int, int, int[]> proxyCall = new Func<int, int, int[]>(proxy.GetNumbers);
asyncProxy = proxyCall.BeginInvoke(max, step, ServiceCallComplete, proxyCall);
}
void ServiceCallComplete(IAsyncResult ar)
{
Func<int, int, int[]> proxyCall = (Func<int, int, int[]>)ar.AsyncState;
int[] numbers = proxyCall.EndInvoke(ar);
SendOrPostCallback addListItem = delegate
{
foreach (int number in numbers)
lstNumbers.Items.Add(number.ToString());
};
_SyncContext.Send(addListItem, null);
}
Now from anywhere else in the form where a user action might take place, I can check the service call thread like this:
private void btnClear_Click(object sender, EventArgs e)
{
if (_AsyncProxy.IsCompleted)
{
lstNumbers.Items.Clear();
progressBar1.Value = 0;
}
}
As you can see, using WCF callbacks, while easy, is not trivial when the work you want to do back at the client is UI related. The first thing you should always ask yourself is, “do I really need to do this?”. There’s a lot of details to take care of and even then, you may not get the effect that you would like. In this last example, pressing the Clear button will simply do nothing. In reality, you may want to disable controls on the form while the service call is taking place. See, there’s quite a lot of worry about.
I hope you join me next week. I have something really cool to show you; but I ain’t gonna tell you what it is.
Until next time…
In the tradition of Scott Hanselman’s “The Weekly Source Code”, I wanted to have a try at a weekly posting that’s all around code and coding techniques. Most of these are probably going to come from stuff I come across in my coding endeavors, but I certainly will accept any contributions from readers. As a warning, some may be short and some may long. The idea is simply to share what I fee are cool coding approaches to problems or to share what I think may be not-so-good approaches to problem. I do promise however, not to be critical about any code I don’t like without having an alternative of a better technique. Also, expect a variety of length in this post-column. They may range from single little code snippets to full-featured solutions and techniques. In any case, they’ll all be filled with code. So to kick off “This Week In Code”, I wanted to show you something that many of you may be familiar with since it’s really not new to .NET 4 (well not all of it anyway). Be that as it may, I think it falls into the category of “still not too regularly used”. The technique I’m going to show you has to do with Lambda expressions in my examples but can certainly be accomplished with anonymous delegates. I’m not here to show you an intro to Lambda expressions, but instead how to mix them with the Action<T> and Func<T> delegates for some cool coding techniques. But first, an introduction to these delegates: The oldest and simplest is Action<T>. This delegate was introduced back in .NET 2.0 and could be used with anonymous delegates. The signature of this delegate is:
public delegate void Action<T>(T arg);
With this pretty free-form signature, the delegate is pretty useful in any scenario where you need to define methods with single signatures. Later after my introduction, I’ll show you how to use this delegate in a cool technique. Now, in .NET 4 Microsoft proved that their developers watch entirely too much Mythbusters, by falling into the creed of “What’s worth doing, is worth over-doing”. I’m not being critical here; I fall into that one all the time myself. In .NET 4, Microsoft expanded on the Action<T> idea and came out with Action<T1, T2>. How’s that overdoing it you ask? Well gentle reader, that’s not the overdoing part, this is: Action<T1, T2, T3>, Action<T1, T2, T3>, and Action<T1, T2, T3, T4>. If you still think that’s not too much, it actually goes out to T8.
The signatures of these delegates are as you may guess, the same as the original but with additional arguments. For example:
public delegate void Action<T1, T2, T3>(T1 arg1, T2 arg2, T3 arg3);
I guess you can call this a “one size fits all” delegate.
Also in .NET 4 came the introduction of the Func<TResult> delegate. The signature of this delegate looks like this:
public delegate TResult Func<TResult>();
There’s also one that accepts a single argument called, Func<T, TResult>, whose signature looks as follows:
public delegate TResult Func<T, TResult>(T arg);
And as you can guess, there are others. Specifically, Func<T1, T2, TResult> and so on all the way to T8 as well.
From what you can see here, the difference between the two delegates is that Action does not offer a return type and Fun does. So what’s this good for? Let me show you.
I’ll start with the Action delegate since its lack of return type make for a bit simpler example. The Action delegate lets you assign a piece of code to a variable for later invocation. The type(s) defined in the generic determine the types of the arguments you use in either an anonymous delegate or a lambda expression. For my examples, I’m going to use lambda expressions and keep things current. Check out this code sample:
Action<IProcessable> process = (processable =>
{
processable.PerformSomethingHere();
foreach (var item in processable.SubItemList)
{
item.DoSomethingWithItem();
}
});
This code is designed to act upon any object that implements the IProcessable interface. It simply calls a method defined by that interface then looks through a list property called SubItemList, which is also defined in the interface. On each item in the list, it calls a method on that item. This idea will be very similar to simply putting this code in its own method, then calling that method with any implementation of IProcessable. However, if you have no need to use this code from multiple outside methods, yet still have to call it multiple times (as you’ll see in a second), defining it this way makes for great encapsulation and isolation. So not let’s say I have an object hierarchy that looks something like this:
Parent.Children[x].GrandChildren
In other words, the Parent object has a collection of Child objects in a property called Children, and each child object has a collection of GrandChild objects in a property called GrandChildren. The Parent, Child, and GrandChild classes all implement the IProcessable interface so I need to execute the code snippet you saw above on all these objects. As I said, it’s easy enough to put the above-code in a method and just called that method from a for-each scenario on my Parent object, but I won’t need that code called from anywhere else and I want to keep all this encapsulated in my one method. I can use the processable variable and invoke it, sending into its argument any instance of the IProcessable interface. The solutions is to do something like this:
Action<IProcessable> process = (processable =>
{
processable.PerformSomethingHere();
foreach (var item in processable.SubItemList)
{
item.DoSomethingWithItem();
}
});
process.Invoke(Parent);
foreach(var child in Parent.Children)
{
proces.Invoke(child);
foreach (var grandChild in child.GrandChildren)
process.Invoke(grandChild);
}
As you can see, the solution is simple and elegant and eliminates the need to have yet another method in your class. If I wanted to pass in another value, like a boolean, into each invocation of the code snippet, I can use the Action<T1, T2> delegate. the lambda expression would then have two variables in it. Here’s the same code modified I the way I’ve just described:
Action<IProcessable, boolean> process = ((processable, b) =>
{
processable.PerformSomethingHere();
foreach (var item in processable.SubItemList)
{
item.DoSomethingWithItem();
item.BooleanPropertu = b;
}
});
process.Invoke(Parent, false);
foreach(var child in Parent.Children)
{
proces.Invoke(child, true);
foreach (var grandChild in child.GrandChildren)
process.Invoke(grandChild, true);
}
It’s very important to wrap the two arguments prior to the lambda’s “goes to” operator using parentheses. Pretty cool huh? Yeah, I think so too . Let’s take a look at using the Func delegate in a very similar fashion. Remember, this delegate defines a return type as well.
The usage scenario for this delegate would be pretty much identical as the previous, only you would have the need to return a value from the invocation. So this time, let me share with you a real-world example on where I’m currently using this delegate. First let me set the scene.
I have a situation where I have to obtain three different database schema query filters (strings) from an incoming dictionary of key-value pairs (IDictionary<string, string>). The dictionary comes into a method and potentially contains three items keyed by “TableFilter”, “CommandFilter” and “ViewFilter”. I say potentially because the incoming dictionary may not contain all of these keys, or none at all, but those that are present contain values that are needed in individual variables. So for example, under normal, boring code circumstances, I would need to check the incoming dictionary (a variable called arguments) to see if it contains the key TableFilter. If it does, I set its value in a string variable called stringFilter. I need to repeat this for the other two keys I’m looking for. Oh, and did I mention that the arguments variable can come into my method as null as well? And, if either the key is not found in the dictionary or the entire dictionary comes in as null, I still need my string variable(s) but with an empty string as their value.
Fine, you’re thinking I can simply check arguments for null first, then do a “contains” check on each key and then set each variable accordingly. Man would that be boring! Let’s do it in a much cooler way:
Func<string, string> filterCheckAndSet = (key =>
{
string filter = "";
if (arguments != null && arguments.ContainsKey(key))
filter = arguments[key];
return filter;
});
string tableFilter = filterCheckAndSet.Invoke("TableFilter");
string commandFilter = filterCheckAndSet.Invoke("CommandFilter");
string viewFilter = filterCheckAndSet.Invoke("ViewFilter");
Here, you can see I’m defining my code snippet in a Func<T, TResult> delegate type, where the first generic defines what I’m sending into the code and the second defines what I’m returning. As you can see, I default my return-type to an empty string, I check the dictionary against it being null and also containing the key I need. The key is one of the arguments I will send into the piece of code. If I find the key, I set the my return variable to the contents of that dictionary item and then return it; yes I can do a return inside code defined in a Func delegate type. Later, I simply invoke the filterCheckAndSet variable, sending in each key, and using the return value in each string variable I need.
That’s it. I’ve found myself using these techniques more and more. But remember, the biggest argument you’ll find against this is that you can accomplish the same with additional method calls. My argument is, yes you can, but if you don’t need a specific level of code re-use, try to limit the scope of the code as it provides better encapsulation. Also, remember that the code snippets are stored in object variables so they can be passed around anywhere you want (should you actually have that particular need).
For the next installment of “This Week In Code”, I want to address a pretty common threading issue when dealing with WCF callbacks, so stay tuned.
Until next time…
My last posting demonstrating what I thought was a pretty cool technique for intercepting WCF operation calls so you can report them on a console; that is when you host on a console application for development. Looking back at that technique, however useful to me, there was something that bugged me. The behaviors I showed you how to write had the reporting-to-the-console part built right into them, and I wasn’t exactly satisfied that. I still maintain the usefulness of reporting every operation call to my host console but wouldn’t it be a more powerful technique to report every operation call and allow the actual host application to do the reporting? That way, whenever you finally deploy you services, you can track operation calls with any hosting application and do whatever you want with them. In the case of a dev-console host, I can still report the calls to the console, but in the case of an IIS or NT-Service deployment I can chose to log them somewhere, even a custom event log. So building on the same technique and code from the previous post, I changed the parameter inspector to raise an event instead of accessing the console. Since the operation behavior is what instantiated and installed the parameter inspector, its job is to bubble the event up through another event. In turn, the service behavior instantiated and installed the operation behavior on every operation so it also takes the information from the captured event and raises its own event. Finally, the console host (in my case), which instantiates and installs the service behavior, captures its event and reports to the console. The end-result in my case is the same, but the ability to simply capture an event from my hosting application gives me the ability to do whatever I want with the information. Remember, each class raises an event to its parent which in turn raises its own event all the way up to the actual host. If you haven’t read my last blog posting, I strongly suggest you go back and read it because I will not be re-explaining the details of the inspector and behavior classes, nor their installation details in this posting.  The first I thing I did was create an event argument class called OperationInformationEventArgs which contains all the information about an operation that I want to send up the chain. This class is used by all three of the other classes, the parameter inspector, the operation behavior, and the service behavior. Here is the code for the event argument class: public class OperationInformationEventArgs : EventArgs
{
public OperationInformationEventArgs(string serviceName, string operationName, DateTime timeStamp)
{
ServiceName = serviceName;
OperationName = operationName;
TimeStamp = timeStamp;
}
public string ServiceName { get; set; }
public string OperationName { get; set; }
public DateTime TimeStamp { get; set; }
}
Next, I renamed the two behavior classes and the parameter inspector so their names were more general and did not imply console-reporting. I called them OperationReportInspector, OperationReportOperationBehavior, and OperationReportServiceBehavior. Also notice that I removed the word Attribute from their class name because I decided to no longer make them attribute capable. Since I’m going to need to do some event wiring, using them in an attribute context would not have worked.
The parameter inspector class now takes the information that it was previously reporting directly to the console, and instead sticks it in the event argument and raises an event.
Here is the code for the new parameter inspector class: public class OperationReportInspector : IParameterInspector
{
public OperationReportInspector(string serviceName)
{
_ServiceName = serviceName;
}
public event EventHandler<OperationInformationEventArgs> ServiceOperationCalled;
protected virtual void OnServiceOperationCalled(OperationInformationEventArgs e)
{
if (ServiceOperationCalled != null)
ServiceOperationCalled(this, e);
}
string _ServiceName = string.Empty;
void IParameterInspector.AfterCall(string operationName, object[] outputs, object returnValue, object correlationState)
{
}
object IParameterInspector.BeforeCall(string operationName, object[] inputs)
{
//Console.WriteLine(string.Format("{0} - '{1}.{2}' operation called.", DateTime.Now.ToLongTimeString(), _ServiceName, operationName));
OnServiceOperationCalled(new OperationInformationEventArgs(_ServiceName, operationName, DateTime.Now));
return null;
}
}
For comparison purposes, I left the old line that wrote out to the console in there and commented it out so you can see the difference.
Now I modified the operation behavior that would install the parameter inspector so just after it instantiates, it wires into the ServiceOperationCalled event. This class also raises an event with the same information (with the same event arguments class in fact) in the method wired to the parameter inspector’s event.
Here is the code for the new operation behavior class: public class OperationReportOperationBehavior : IOperationBehavior
{
public event EventHandler<OperationInformationEventArgs> ServiceOperationCalled;
protected virtual void OnServiceOperationCalled(OperationInformationEventArgs e)
{
if (ServiceOperationCalled != null)
ServiceOperationCalled(this, e);
}
void IOperationBehavior.AddBindingParameters(OperationDescription operationDescription, BindingParameterCollection bindingParameters)
{
}
void IOperationBehavior.ApplyClientBehavior(OperationDescription operationDescription, ClientOperation clientOperation)
{
}
void IOperationBehavior.ApplyDispatchBehavior(OperationDescription operationDescription, DispatchOperation dispatchOperation)
{
string serviceName = dispatchOperation.Parent.Type.Name;
OperationReportInspector inspector = new OperationReportInspector(serviceName);
inspector.ServiceOperationCalled += inspector_ServiceOperationCalled;
dispatchOperation.ParameterInspectors.Add(inspector);
}
void IOperationBehavior.Validate(OperationDescription operationDescription)
{
}
void inspector_ServiceOperationCalled(object sender, OperationInformationEventArgs e)
{
OnServiceOperationCalled(e);
}
}
Finally, I modified the service behavior class so just after it instantiates the operation behavior, it wires its event to a method where its own event is raised; again with the same event argument information.
Here is the code for the new service behavior class: public class OperationReportServiceBehavior : IServiceBehavior
{
public event EventHandler<OperationInformationEventArgs> ServiceOperationCalled;
protected virtual void OnServiceOperationCalled(OperationInformationEventArgs e)
{
if (ServiceOperationCalled != null)
ServiceOperationCalled(this, e);
}
void IServiceBehavior.AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, System.Collections.ObjectModel.Collection<ServiceEndpoint> endpoints, BindingParameterCollection bindingParameters)
{
}
void IServiceBehavior.ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
{
foreach (ServiceEndpoint endpoint in serviceDescription.Endpoints)
foreach (OperationDescription operation in endpoint.Contract.Operations)
{
OperationReportOperationBehavior behavior = new OperationReportOperationBehavior();
behavior.ServiceOperationCalled += behavior_ServiceOperationCalled;
operation.Behaviors.Add(behavior);
}
}
void IServiceBehavior.Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
{
}
void behavior_ServiceOperationCalled(object sender, OperationInformationEventArgs e)
{
OnServiceOperationCalled(e);
}
}
So now, all that is left to do is to change the actual console host application so when it instantiates and installs the service behavior, it wires into its ServiceOperationCalled event, then displays the information to the console using the wired method.
Here’s the new code for the console host: OperationReportServiceBehavior behavior = serviceHost.Host.Description.Behaviors.Find<OperationReportServiceBehavior>();
if (behavior == null)
{
behavior = new OperationReportServiceBehavior();
behavior.ServiceOperationCalled += behavior_ServiceOperationCalled;
serviceHost.Host.Description.Behaviors.Add(behavior);
}
void behavior_ServiceOperationCalled(object sender, OperationInformationEventArgs e)
{
Console.WriteLine(string.Format("{0} - '{1}.{2}' operation called.",
e.TimeStamp.ToLongTimeString(), e.ServiceName, e.OperationName));
}
As I said, the end-result is the same as in my previous posting but now the hosting application can chose to do what it wants with the contents of the event argument. In my humble opinion, what was a cool technique is now a cooler technique.
Until next time…
Note: Using a Console app for hosting should be done for development only ! Now that the disclaimer is out of the way, I currently doing some development work for a customer and I had the need to know every time any of my services receives a call. Since I do my development using a console application for service hosting, it was easy enough to write out to the console from each service operation. Of course, putting code in every method was possible but not only would it be time consuming, to turn it off later would be a pain. The answer needed to be something that gets hit on every operation. Since WCF is essentially one giant inversion of control container, I knew there was a point I could tap into before any operation call. Enter behaviors ! This turned out to be a multi-step process but once it’s in my library of WCF stuff, I can reuse it and it actually turned out to be quite cool. I’ll explain each step and the reasons for the step.
Step 1 – Write a custom Parameter Inspector The first class you need to write is one that implements the IParameterInspector which is in the System.ServiceModel.Dispatcher namespace. This class will later be installed in such a way that it gets hit on every operation call. The operation name is one of the arguments you have access to, as well as all the operation arguments which I don’t need in this case. The methods in this implementation are BeforeCall and AfterCall, and it is the BeforeCall that I’m interested in. The code I’ll place in this method very simply outputs something out to the console using Console.Writeline. Unfortunately the name of the service is not passed into this method so I need to get that into this class using a custom constructor; you’ll see how I’ll get it to the class later. Here’s the code for my ConsoleReportInspector class: public class ConsoleReportInspector : IParameterInspector
{
public ConsoleReportInspector(string serviceName)
{
_ServiceName = serviceName;
}
string _ServiceName = string.Empty;
void IParameterInspector.AfterCall(string operationName, object[] outputs, object returnValue, object correlationState)
{
}
object IParameterInspector.BeforeCall(string operationName, object[] inputs)
{
Console.WriteLine(string.Format("{0} - '{1}.{2}' operation called.", DateTime.Now.ToLongTimeString(), _ServiceName, operationName));
return null;
}
}
Step 2 – Install the class using an Operation Behavior
In order to install the parameter inspector, I’ll need to write a custom operation behavior class. This is a class that implements the IOperationBehavior interface. You need to remove the throw to NotImplementedException from all the methods; and the method of concern here is ApplyDispatchBehavior.
The name of the service being called is accessible through the Parent property of the dispatchOperation argument. I need to instantiate my ConsoleReportInspector class and send the service name into the constructor I added earlier. Afterward, I just need to add my parameter inspector class to the list of parameter inspectors accessible in this behavior.
I also inherited this class from the System.Attribute class so I can use it as an operation behavior attribute on individual operations if I wanted. This is just for flexibility since I plan on hooking this into a service so it affects all operations.
Here’s the code for my ConsoleReportOperationBehaviorAttribute class:
[AttributeUsage(AttributeTargets.Method)]
public class ConsoleReportOperationBehaviorAttribute : Attribute, IOperationBehavior
{
void IOperationBehavior.AddBindingParameters(OperationDescription operationDescription, BindingParameterCollection bindingParameters)
{
}
void IOperationBehavior.ApplyClientBehavior(OperationDescription operationDescription, ClientOperation clientOperation)
{
}
void IOperationBehavior.ApplyDispatchBehavior(OperationDescription operationDescription, DispatchOperation dispatchOperation)
{
string serviceName = dispatchOperation.Parent.Type.Name;
dispatchOperation.ParameterInspectors.Add(new ConsoleReportInspector(serviceName));
}
void IOperationBehavior.Validate(OperationDescription operationDescription)
{
}
}
As-is, I can simply decorate a service operation with [ConsoleReportOperationBehavior] and if hosted on a console application, you’ll see output to the console when the decorated operation is called.
Step 3 – Install the operation behavior on all operations using a Service Behavior
Next I need to write a service behavior. This is a behavior that gets installed when the service loads (the host is opened). The job of this behavior is to install my operation behavior on all the service operations. A service behavior is a class that implement the IServiceBehavior interface. Like before, I’ll remove the exception calls and once again the method I’m interested in is ApplyDispatchBehavior.
I’m going to iterate through all the endpoints of this service, which are accessible through the serviceDescription argument, and for each endpoint I will iterate through the operations of the contract of each endpoint. To each operation I will add an instance of my ConsoleReportOperationBehaviorAttribute class.
This class too I will inherit from Attribute so I can use it to decorate a service in the case that I wanted to take this approach at some time.
Here’s the code for my ConsoleReportServiceBehaviorAttribute class:
[AttributeUsage(AttributeTargets.Class)]
public class ConsoleReportServiceBehaviorAttribute : Attribute, IServiceBehavior
{
void IServiceBehavior.AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, System.Collections.ObjectModel.Collection<ServiceEndpoint> endpoints, BindingParameterCollection bindingParameters)
{
}
void IServiceBehavior.ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
{
foreach (ServiceEndpoint endpoint in serviceDescription.Endpoints)
foreach (OperationDescription operation in endpoint.Contract.Operations)
operation.Behaviors.Add(new ConsoleReportOperationBehaviorAttribute());
}
void IServiceBehavior.Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
{
}
}
Step 4 – Apply the service behavior to any service I want programmatically at the host
Whatever approach you take to hosting, all you need to do is access each instance of ServiceHost and add the service behavior to the list of behaviors in the host. I have my own techniques for hosting which include some custom declarative stuff to allow me to turn hosting on and off at will through config. I also like to separate the accumulation of my ServiceHost instances from the actual application that will do the hosting. This way I can move it to a Windows Service when I’m ready to go to production.
Here’s the code that installs the behavior:
ConsoleReportServiceBehaviorAttribute behavior = serviceHost.Host.Description.Behaviors.Find<ConsoleReportServiceBehaviorAttribute>();
if (behavior == null)
host.Description.Behaviors.Add(new ConsoleReportServiceBehaviorAttribute());
The host variable is an instance of ServiceHost. I perform the code above in between a config check so I can toggle it off at will.
The end result is quite cool since when turned on, every call to any of your services will be shown on the console.
Until next time…
|