Tampilkan postingan dengan label C#. Tampilkan semua postingan
Tampilkan postingan dengan label C#. Tampilkan semua postingan

Jumat, 22 Oktober 2010

Extending uNhAddIns ComponentBehavior (Asynchronous Behavior)

When working on WPF MVVM, sometime it is necessary to add asynchronous behavior to ViewModel, but usually programmer facing some problems:
  • The need of Dispatcher in the ViewModel make it harder to unit test.
  • Unit testing an asynchronous ViewModel is hard and tricky.


By extending uNhAddins ComponentBehavior I can make my ViewModel easy to unit test. Because the asynchronous behavior can be turn ON and OFF. Turn it ON when used in the real application and turn it OFF when used in the unit testing.

Here is the code:
[Behavior(1)]
public class AsynchronousBehavior : IInterceptor
{
SynchronizationContext Context;

public AsynchronousBehavior()
{
Context = SynchronizationContext.Current ?? 
new SynchronizationContext();
}

public void Intercept(IInvocation invocation)
{
object[] attributes = invocation
.Method.GetCustomAttributes(true);
if (attributes.Any(x => x is UIThreadAttribute))
{
Context.Post(o => invocation.Proceed(), null);
return;
}
if (attributes.Any(x => x is BackgroundThreadAttribute))
{
ThreadPool.QueueUserWorkItem(o => 
invocation.Proceed(), null);
return;
}
invocation.Proceed();
}
}


Pretty simple code eh? but how to use it? here it is:

public class MyAsyncViewModel
{
//Property keep simple using 
//NotifyPropertyChangedBehavior
public virtual IList MyProperty { get; set; }

[BackgroundThread]
public virtual void RunLongTask()
{
//Long runing task called here.
UpdateProperty(result);
}

[UIThread]
protected virtual void UpdateProperty(string result)
{
//change collection require in UI thread
MyProperty.Remove(0);
}
}


See, ViewModel is free form Dispatcher. The UIThread and BackgroundThread is only a simple attribute

public class UIThreadAttribute : Attribute {}
public class BackgroundThreadAttribute: Attribute {}


But how the magic is work? in uNhAddIns everything is only a matter of the Guy Wire:

public void Install(IWindsorContainer container, IConfigurationStore store)
{
container.Register(Component.For().LifeStyle.Transient);

var behaviorStore = new BehaviorDictionary();
behaviorStore.For()
.Add()
.Add();
container.Register(Component.For().Instance(behaviorStore));
container.Register(Component.For().LifeStyle.Transient);
}


How the ON and OFF work? just remove the AsynchronousBehavior in the BehaviorDictionary registration then your ViewModel will work synchronously.

I really appreciate people work at uNhAddIns, seems like the library built with an ancient manuscript. You only need to spell simple script then a great thing happen.

NOTE:
Using [UIThread] actually not necessary, in fact accessing ViewModel property from different thread is OK but change collection from different thread is causing exception, please refer to this old blog for more information.

Senin, 06 September 2010

Mammoth Extensibility Infrastructure (Plugability and Integration Testing)

Open Architecture


In my project there is an extensibility infrastructure. It makes application possible to load assembly at runtime. Actually my first thought was using MEF, but after done further investigation I found that MEF didn't match with what I needed.

Extensibility Infrastructure


What so special about that library is the ability to intercept its object creation. So I can possibly: Create proxy object of the add-ins or Mock the add-ins when doing integration testing take a look at the ExtensionResolver class for more detail.

The main idea of the extensibility resolver is using IObjectCollectionCreator, so in the implementation it can be override to match what I need.

Proof of Concept


Look at the implementation of the ObservableObjectCreator by assign this object to extension resolver I can get an object support WPF databinding whereas inherrited from INotifyPropertyChanged and all its generic collection property will change to ObservableCollection.

The most interesting one is for Integration Testing. I'm not sure if it is can be done in MEF, but by mammoth extensibility infrastructure I make AssertObjectInterceptor whereas it will inject a AssertCallback to the dummy Add-Ins. so whenever each method of dummy Add-Ins calls by service, AssertCallback will send Assert event, further i can put Assertion on that event handler. Take a look at the test fixture:

AssertCallback assertCallback;
ResponderService target;
bool HasNoError;
ManualResetEvent resetEvent;

[TestInitialize]
public void Initialize()
{
assertCallback = new AssertCallback();
resetEvent = new ManualResetEvent(false);
HasNoError = true;
target = new ResponderService();
//the most inportant thing is here
target.ObjectCreator =
new AssertObjectCreator(assertCallback);
target.Error += (s, e) =>
{ HasNoError = false; resetEvent.Set(); };
}

[TestMethod]
public void WhenServiceRun_ShouldLoginAllServices()
{
bool isLoginCalled = false;
assertCallback.Assert += (s, e) =>
{
if (e.MethodName == MockService.LOGIN_METHOD)
{
isLoginCalled = true;
resetEvent.Set();
}
};

target.Run();
resetEvent.WaitOne();

mock.VerifyAll();
Assert.IsTrue(HasNoError);
Assert.IsTrue(isLoginCalled);
}


and Implementation of the MockService is:


public class MockService : IMessagingService
{
//some code has been cutted for clairity
public static string SEND_MESSAGE_METHOD =
"MockService.SendMessage";
public virtual void SendMessage(
string targetEmail, string message)
{
}
}



That's all, the library a bit far from simplicity (like MEF done with Attribute) but here I win the flexibility.

Happy Codding.