Showing posts with label development. Show all posts
Showing posts with label development. Show all posts

Friday, April 29

Per Developer App.Config

We are working on C# project which use app.config to configure the way our application works.
Since we are using shared source control system we notice we each step on each others those when it comes to changes of the app.config. Each developer change things like the address of some service, which modules to load, etc.
One possible way is to make sure you are not checking-in your modified app.config, but that tedious.

We wanted to have the normal app.config with some reasonable default settings and have per developer app.config file like app_ido.config which will be used if present.

After reading Microsoft.Common.targets for a while I've found target called PrepareForBuild. I've notice that Microsoft were kind enough to use property called AppConfig if you define it. If you do not define it they try to find file called app.config which has build action of either None or Content (in that order).

So, I've create a new Console application, add to it app.config file and put some appSettings in it just to be able to tell which app.config I am using. I've then open the csproj file for edit and add new element inside the first PropertyGroup element called AppConfig and set it to 123. When I've compile it I've got an error that Application Configuration file "123" is invalid and could not be found. That was the way, the rest was easy.

I've change that property element to this:
<AppConfig Condition="Exists('App_$(USERNAME).config')">App_$(USERNAME).configAppConfig>


This did exactly what we needed. We chose to use the current Windows username as our variable to identify each developer. If file with the name of the developer is found - we use it, otherwise we fallback to normal app.config.

There was only one question open which is should we keep the developers app.config files in the source control system or not?

After some thinking we decide not to check them into the source control because those files are dispensable and can only cause harm like merge conflicts.

I hope this will help other developers looking for this behaviour.

You can download sample application, just change the file called app_Ido.config from Ido to your name and your good to go. Remember to rebuild the project after you the file name to see the effect.

Sunday, August 17

CLR Weak Event

Since .NET 1.0 Microsoft provide a standard way to register for events of objects.
One of the biggest problem of using the standard event pattern is that the lifetime of the subscriber become governed by the lifetime of the source.
There are several articles about how to overcome this problem, also Microsoft has add a new class to .NET 3.0 called WeakEvent.
I have found WeakEvent class not feat to my needs since it inherit from DependencyObject which is WPF specific object and thus not suited for usage in general program - not related to WPF.
Also, after reading some articles on the net about this issue, I have realized that most of the solution came from the source side, that is changing the object exposing the event to allow weak events, but this is not always the case - sometime you need to you compiled, closed, even seal object and to register to its events weakly.

So, the solution was involved around WeakReference class.
The idea is simple, we want to register to event of source (call it S) with the receiver (call it R).
In classic .NET event S always keep strong reference to R, usually R also keep strong reference to S.
We need to break the strong reference between S and R so that even when S is still alive, it will not keep R alive any longer then it really needs.
We do this by creating new class (call it M) which will mediate the event from the source to the receiver. M will be register to the event on S and will keep a weak reference to R. M will also need to check if R is still alive before dispatching the event.

The code:

class S
{
public event EventHandler SomeHappen;
}

class R
{
R(S s)
{
new M(this, s);
}

private void HandleSomeHappen(object sender, EventArgs e)
{
...
}

private class M
{
private WeakReference _r;
private S _s;

M(R r, S s)
{
_s = s;
_r = new WeakReference(r);
s.SomeHappen += DispatchSomeHappen;
}

private void DispatchSomeHappen(object sender, EventArgs e)
{
R r = (R)_r.Target;
if (r == null) {
_s.SomeHappen -= DispatchSomeHappen;
} else {
r.HandleSomeHappen(sender, e);
}
}
}
}

As you can see this solution is not generic.
I used a private class to dispatch the events sine I want to be able to leave the handle method in the receiver class private or protected.
Most of the work is done in DispatchXXX method which first check if the target has been garbage collected already, in this case we unregister from the event and leave M to be collected next. Otherwise we dispatch the event to the receiver object and let it handle the event.

I'm trying to make this solution more generic, but I yet to find the way.