Archive for the 'Uncategorized' Category

16
Oct
12

Coroutines are dead. Long live Coroutines.

As many of you may have already heard, Caliburn.Micro was recently ported to WinRT thanks to Nigel Sampson and Keith Patton.

Either if you are doing Windows 8 development or working with WPF and .NET Framework 4.5, you are probably eagerly playing working with the powerful asynchronous programming support in Visual Studio 2012. (Not yet? Go study it NOW).

For those using Caliburn and Caliburn.Micro, a very neat kind of asynchronous programming has been available since 2009: have a look at this Rob’s blog post introducing IResult and Coroutines, one year before Async CTP!

But now async/await stuff is going to be mainstream; does it mean that IResult and Coroutines are becoming useless?
My initial opinion is that they could be kept just for backward compatibility, but they turned out to be still quite important for some reasons.

Access to execution context

In several scenarios the action defined in the ViewModel requires to gain direct access to the view or to the element triggering the action itself.
The view instance could be obtained using GetView method on Screen class (or implementing IViewAware), but the triggering element instance is not that easy to reach.

Moreover, while in some cases using an “Model-View-Presenter-like” approach is the only viable solution, generally speaking ViewModels should not control the UI directly, nor deal with presentation concerns at all.

Custom IResult, instead, provides an easy access to a class called ActionExecutionContext, which contains all the objects involved into the action execution: the containing view, the triggering element, the ViewModel instance, the method called, etc.
So, while creating ad-hoc IResults for simple asynchronous service calls could be tedious, using custom, reusable IResult to isolate UI concerns is quite effective, and helps to clean out ViewModels code.

Testability

It’s entirely possible testing async code written using async/await, usually replacing real services with mocks. Yet, using an IEnumerable<IResult> in the ViewModel allows to just test the returned “sequence”, without actually executing each IResult.

Action execution “wrapping”

Caliburn.Micro can map (using conventions or an explicit DSL) an event occurring on the UI side to a method call on the ViewModel side.
As a consequence, it’s very easy to turn a simple void method into an asynchronous one (async void or async Task), and let Caliburn.Micro to start its execution.

I don’t recommend this approach, however: this way, indeed, the action execution (from CM’s point of view) completes as soon as a Task object is created, while the actual async method execution usually take longer. Also, exceptions thrown during execution may go unobserved (see http://blogs.msdn.com/b/pfxteam/archive/2011/09/28/10217876.aspx) because the Task object is not available anymore.

For these reasons I wrote a simple extension taking care of it; the strategy I chose is to customize CM’s action invocation code, in order to intercept async methods returning Tasks and wrap them into an IResult.
This way I could simply take advantage of the existing infrastructure; in particular, I can use the builtin notification of Coroutines completion (Coroutine.Complete static event), which also bring information about possible exception occurred.

Here the relevant code:

public static class AsyncAwaitSupport
{
	public static void Hook()
	{

		ActionMessage.InvokeAction = context =>
		{

			var values = MessageBinder.DetermineParameters(context, context.Method.GetParameters());
			var returnValue = context.Method.Invoke(context.Target, values);

			var task = returnValue as Task;
			if (task != null)
			{
				returnValue = new TaskResult(task);
			}

			var result = returnValue as IResult;
			if (result != null)
			{
				returnValue = new[] { result };
			}

			var enumerable = returnValue as IEnumerable;
			if (enumerable != null)
			{
				Coroutine.BeginExecute(enumerable.GetEnumerator(), context);
				return;
			}

			var enumerator = returnValue as IEnumerator;
			if (enumerator != null)
			{
				Coroutine.BeginExecute(enumerator, context);
				return;
			}
		};
	}

	private class TaskResult : IResult
	{
		Task task;
		public TaskResult(Task task)
		{
			if (task == null) throw new ArgumentNullException("task");
			this.task = task;
		}

		public event EventHandler Completed = delegate { };

		public void Execute(ActionExecutionContext context)
		{
			task.ContinueWith(t =>
			{
				Completed(this, new ResultCompletionEventArgs {
                                            WasCancelled = t.IsCanceled,
                                            Error = t.Exception }
                                       );
			});
		}
	}

}

The extension is hooked during the bootstrapper initialization:

protected override void Configure()
{
    base.Configure();

    AsyncAwaitSupport.Hook();

    //...
}

Once I have this in place, I could translate the following code (taken from CoroutineViewModel.cs inside Caliburn.Micro.WinRT.Sample):

public IEnumerable ExecuteCoroutine()
{
	yield return new VisualStateResult("Loading");
	yield return new DelayResult(2000);
	yield return new VisualStateResult("LoadingComplete");
	yield return new MessageDialogResult("This was executed from a custom IResult, MessageDialogResult.", "IResult Coroutines");
}

into something like this:

public async Task ExecuteTask()
{
	this.SetVisualStateOnView("Loading");

	await Task.Delay(2000);

	this.SetVisualStateOnView("LoadingComplete");

	//This is just a sample: I don't actually recommend calling UI code from here in real code.
	var dialog = new Windows.UI.Popups.MessageDialog("This was executed with a regular MessageDialog.", "Async/await");
	await dialog.ShowAsync();
}

[Here the same post in Italian language]

Advertisements
21
May
10

DomusDotNet: a new italian .NET community based in Rome

logo_no_pl

Last friday, during the Visual Studio 2010 Community Tour – Rome, we presented DomusDotNet, a new italian .NET community based in Rome.

Our wish is to create a place to share informations, news, technical experiences and meet (both in the web and in the "real" world) other people interested in professional improvement.

If you speak Italian, please have a look at our website www.domusdotnet.org; we have been working hard (and late into the night…) to complete the beta version on schedule, so please don’t be too severe upon it!

Comments and suggestions are welcome!

(some of) DomusDotNet members

01
Mar
10

Binding to an interface property with WPF

I received a tweet from José in reply to my comment about the ugliness of the WPF syntax to bind to an interface property, when the interface is explicitly implemented.

He reminded me that I tried very hard -and uselessly- to find a workaround for this, and one day the correct syntax just popped out from a blog I was reading (I can’t remember who the benefactor was… I would have liked to thank him here).

Now, the ill-famed syntax:

{Binding Path=(myns:IMyInterface.MyProperty)}

18
Sep
09

WPF binding to a Windsor proxied component

WPF binding is very powerful but has some annoying issues. This time I faced with a well known one: binding to an explicitly implemented interface member doesn’t work:

public interface IFoo {
int BarsCount {get;}
}

public class Foo:IFoo {
int IFoo.BarsCount {
return 3;
}
}

<TextBox DataContext=[set to some Foo instance] Text={Binding Path=BarsCount} />

This way the textbox is not filled; while annoying, it could be fixed implementing interface implicitly:


public class Foo:IFoo {
public int BarsCount {
return 3;
}
}

Sometimes it is not possible, because we can’t control concrete class implementation. This is the case when the concrete class is dynamically generated proxy.

In a project of mine I use Castle Project’s Windsor Container, that relies on Castle DynamicProxy for its AOP/intercepion features (which I use for cross-cutting concern implementation).
In this project all the presenters are registered in the container with related interfaces; when I configure an interceptor for a presenter, the concrete class returned by the container is not the registered implementation, but a dynamically generated proxy (implementing the registered interface) forwarding all method calls to a wrapped instance of my hand-written presenter (thus allowing methods interception).

This interception style is called Interface Proxy  (see excellent Krzysztof Koźmic tutorial on Castle DynamicProxy proxy capabilities).

This way, however, previously working binding to the presenter stops running: presenter instance no longer has expected (at least by WPF) properties in its public interface.

The solution I found (yet not very general) is to leverage another interception style, Class Proxy, used by Windsor when a component is registered without a corresponding interface. In this scenario, the generated proxy is a dynamically generated subclass of the concrete component registered; this way only virtual method could be intercepted, but the public interface of the component is preserved (and so the WPF binding operation).

The choice of the interception style is taken by a well defined (and pluggable) Windsor component: IProxyFactory. So I implemented a custom IProxyFactory, inheriting the default one and altering its behavior when the registered component is decorated with a certain custom attribute; this attribute specifies that a Class Proxy style interception should be used. Here the implementation:


[AttributeUsage(AttributeTargets.Class)]
public class ForceClassProxyAttribute : Attribute { }

//Force class proxy if service implementor is decorated with ForceClassProxyAttribute
//Is a workaround for WPF binding not seeing interface members
public class WindsorProxyFactory : DefaultProxyFactory
{
public override object Create(Castle.MicroKernel.IKernel kernel, object target, Castle.Core.ComponentModel model, Castle.MicroKernel.CreationContext context, params object[] constructorArguments)
{
if (this.ShouldForceClassProxy(model, target))
return CreateForcingClassProxy(kernel, target, model, context, constructorArguments);
else
return base.Create(kernel, target, model, context, constructorArguments);
}

protected virtual object CreateForcingClassProxy(Castle.MicroKernel.IKernel kernel, object target, Castle.Core.ComponentModel model, Castle.MicroKernel.CreationContext context, params object[] constructorArguments)
{
object proxy;

IInterceptor[] interceptors = ObtainInterceptors(kernel, model, context);

ProxyOptions proxyOptions = ProxyUtil.ObtainProxyOptions(model, true);
ProxyGenerationOptions proxyGenOptions = CreateProxyGenerationOptionsFrom(proxyOptions);

CustomizeOptions(proxyGenOptions, kernel, model, constructorArguments);

Type[] interfaces = proxyOptions.AdditionalInterfaces;
proxy = generator.CreateClassProxy(model.Implementation, interfaces, proxyGenOptions,
constructorArguments, interceptors);

CustomizeProxy(proxy, proxyGenOptions, kernel, model);

return proxy;
}

protected bool ShouldForceClassProxy(Castle.Core.ComponentModel model, object target)
{

return model.Implementation
.GetCustomAttributes(typeof(ForceClassProxyAttribute), true)
.Any();
}
}

Then I simply provide this custom IProxyFactory implementation when container instance is created:


var container = new WindsorContainer(new IniziativeInformatiche.Core.WindsorProxyFactory());


Comments and suggestions are welcome, if someone will ever get here 🙂

Edit:

It seems that binding to interface members could be done with the syntax:


{Binding Path=(local:IFoo.BarsCount)}

I should better investigate, even though this way I should fix all existing views…

15
Sep
09

Stock Trader with Caliburn – code repository

I set up a project repository to publish the code:
http://code.google.com/p/caliburn-stock-trader/

03
Sep
09

Done.

First step done.

In the last weeks I finally decided to take the time to open a blog, mainly focused (for now, at least) on .Net programming.

My main goals are:

  • share thoughts, ideas, suggestion about technical .Net stuff (and hopefully receive some feedback);
  • improve my poor English;
  • use some of my (scanty) spare time for a long-term task.

I hope this will become an interesting space. Wish me to succeed!




December 2017
S M T W T F S
« Oct    
 12
3456789
10111213141516
17181920212223
24252627282930
31  

%d bloggers like this: