Showing posts with label C. Show all posts
Showing posts with label C. Show all posts

Thursday, 29 May 2008

WeakEvent - you wish it was here

At the first glance .NET events are an easy and harmless way to decouple components. The former statement is true but the latter is not. The reason is that whenever an instance of a class subscribes to an event published by another class a strong link between these two is established. By strong link I mean that the subscriber(listener) won't get garbage-collected as long as the publisher is alive. The only way to break that link is to unsubscribe from the event which might be easily omitted as the link is not explicit. Additionally there are cases when explicit(deterministic) cancellation of subscription is impossible. If additionally the publisher is a long living object than we might face a memory leak. In ideal world there would be a way of specifying that a subscription is weak which would mean that if the subscription is the only link to an object then the object can be garbage-collected and the subscription can be deleted. .NET does not provide that facility out of the box but fortunately it provides building blocks that in most cases let us build a good enough solution. The idea is to intercept calls that add and remove subscribers from/to an event and create a weak link between subscribers and publisher instead of the default, strong one.
When you define an event you don't have to write add/remove methods on your own because C# compiler generates them automatically. Basically the following code snippet:

public event EventHandler <EventArgs> MyEvent;

is just "syntactic sugar" that C# compiler transforms to much more verbose form. You can find detailed description of this process in CLR via C#  by Jeffrey Richter. From our perspective the most important thing is that we can overwrite the default behavior of the compiler and inject our own implementation of Add and Remove methods in a way that is completely transparent to subscribers. SomeClass and Subscriber classes show how it can be done. Don't worry about WeakEvent<T> class as it will be explained later.

public class SomeClass
{
private WeakEvent <EventArgs> myWeakEvent;
public event EventHandler <EventArgs> MyWeakEvent
{
add
{
myWeakEvent.Add(value);
}

remove
{
myWeakEvent.Remove(value);
}
}
private void SomeMethodThatNeedsToRiseMyWeakEvent()
{
OnMyWeakEvent(new EventArgs());
}

protected void OnMyWeakEvent(EventArgs args)
{
myWeakEvent.Invoke(args);
}
}
public class Subscriber
{
private SomeClass someClass;
public Subscriber()
{
someClass = new SomeClass();
someClass.MyWeakEvent += Method;
}

private void Method(object sender, EventArgs e)
{
}
}


Add and Remove methods take a delegate as the input parameter. Every .NET delegate is an object with 2 properties. One of them is a reference to the target of the delegate(the object the delegate will be called on) and the second one is a description of the method which is provided as an instance of System.Reflection.MethodInfo class. Static delegates have the target property set to null. The target field is the root of all evil as it keeps the subscriber alive(it is a strong reference to the object the delegate will be called on). Fortunately .NET framework provides a class that can act as man in the middle between the method and its target which lets us break the direct link between them.
The class that makes it possible is called (no surprise) System.WeakReference. An instance of System.WeakReference class keeps a weak reference(instead of strong) to the object that is passed to its constructor. The weak reference can be transformed into the strong reference by accessing its Target property and storing its value in an ordinary variable. In this way we resurrect the object. If the object is already garbage-collected then the property returns null. All aforementioned functionality is encapsulated in a custom class that I called WeakDelegate.

internal class WeakDelegate
{
private WeakReference target;
private MethodInfo method;

public object Target
{
get
{
return target.Target;
}
set
{
target = new WeakReference(value);
}
}

public MethodInfo Method
{
get { return method; }
set { method = value; }
}
}

WeakEvent<T> is a class that takes advantage of WeakDelegate class to solve the problem outlined in the first paragraph. Its below implementation is rather straightforward but 2 pieces of code might need some explanation. The first one is inside Invoke method. Internally we store instances of WeakDelegate class which means that we can not invoke them directly and every time one of them needs to be executed we have to assemble an instance of  System.Delegate class. I don't know if the way the code creates delegates is the fastest one but I measured the execution time of that statement and the average time was 0.005384 ms per delegate which is fast enough for me. The second one is related to the fact that the locking is done in a way that prevents threads from waiting forever. If a thread can't enter the critical section within 15 seconds then it throws an exception. The rationale behind that approach is explained here.

public class WeakEvent <T> where T : EventArgs
{
private readonly List <WeakDelegate> eventHandlers;
private readonly object eventLock;

public WeakEvent()
{
eventHandlers = new List <WeakDelegate>();
eventLock = new object();
}

public void Invoke(T args)
{
ExecuteExclusively(delegate
{
for (int i = 0; i < eventHandlers.Count; i++)
{
WeakDelegate weakDelegate = eventHandlers[i];
// don't move this line to the ELSE block
//as the object needs to be resurrected
Object target = weakDelegate.Target;

if (IsWeakDelegateInvalid(target, weakDelegate.Method))
{
eventHandlers.RemoveAt(i);
i--;
}
else
{
Delegate realDelegate = Delegate.CreateDelegate(typeof(EventHandler <T>),
target, weakDelegate.Method);
EventHandler <T> eventHandler = (EventHandler <T>)realDelegate;
eventHandler(this, args);
}
}
});
}

public void Remove(EventHandler <T> value)
{
ExecuteExclusively(delegate
{
for (int i = 0; i < eventHandlers.Count; i++)
{
WeakDelegate weakDelegate = eventHandlers[i];
Object target = weakDelegate.Target;

if (IsWeakDelegateInvalid(target, weakDelegate.Method))
{
eventHandlers.RemoveAt(i);
i--;
}
else
{
if (value.Target == target && value.Method == weakDelegate.Method)
{
eventHandlers.RemoveAt(i);
i--;
}
}
}
});
}

public void Add(EventHandler <T> value)
{
ExecuteExclusively(delegate
{
RemoveInvalidDelegates();

WeakDelegate weakDelegate = new WeakDelegate();
weakDelegate.Target = value.Target;
weakDelegate.Method = value.Method;

eventHandlers.Add(weakDelegate);
});
}

private void RemoveInvalidDelegates()
{
for (int i = 0; i < eventHandlers.Count; i++)
{
WeakDelegate weakDelegate = eventHandlers[i];

if (IsWeakDelegateInvalid(weakDelegate))
{
eventHandlers.RemoveAt(i);
i--;
}
}
}

private void ExecuteExclusively(Operation operation)
{
bool result = Monitor.TryEnter(eventLock, TimeSpan.FromSeconds(15));

if (!result)
{
throw new TimeoutException("Couldn't acquire a lock");
}

try
{
operation();
}
finally
{
Monitor.Exit(eventLock);
}
}

private bool IsWeakDelegateInvalid(WeakDelegate weakDelegate)
{
return IsWeakDelegateInvalid(weakDelegate.Target, weakDelegate.Method);
}

private bool IsWeakDelegateInvalid(object target, MethodInfo method)
{
return target == null && !method.IsStatic;
}
}



You might have noticed that there is some housekeeping going on whenever one of Add, Remove or Invoke methods is called. The reason why we need to do this is that WeakEvent<T> keeps a collection of WeakDelegate objects that might contain methods bound to objects(targets) that have been garbage-collected. In other words we need to take care of getting rid of invalid delegates on our own. Solutions to this problem can vary from very simple to very sophisticated. The one that works in my case basically scans the collection of delegates and removes invalid ones every time a delegate is added, removed or the event is invoked. It might sound like overkill but it works fine for events that have around 1000-5000 subscribers and it's very simple. You might want to have a background thread that checks the collection every X seconds but then you need to figure out what is the value of X in your case. You can go even further and keep the value adaptive but then your solution gets even more complicated. In my case the simplest solutions works perfectly fine.
Hopefully this post will save someone an evening or two :).

Tuesday, 12 February 2008

C# generics - parameter variance, its constraints and how it affects WCF

CLR generics are great and there is no doubt about that. Unfortunately, C# doesn't expose the whole beauty of it because all generic type parameters in C# are nonvariant though from CLR point of view they can be marked as nonvariant, covariant or contravariant. You can find more details about that topic here and here. In short the "nonvariant" word means that even though type B is a subtype of type A then SomeType<B> is not a subtype of SomeType<A> and therefore the following code won't compile:

List <String> stringList = null;
List <object> objectList = stringList; //this line causes a compilation error

Error 1 Cannot implicitly convert type 'System.Collections.Generic.List<string> to 'System.Collections.Generic.List<object>. An explicit conversion exists (are you missing a cast?)

The generics are all over the place in WCF and you would think that this is always beneficial to all of us. Well, it depends. One of the problems I noticed is that you can not easily handle generic types in a generic way. I know it does not sound good :) but that's what I wanted to say. The best example is ClientBase<T> that is the base class for auto generated proxies. VS.NET generates a proxy type per contract(interface) which might lead to a situation where you need to manage quite a few many different proxies. Let's assume that we use username and password as our authentication method and we want to have a single place where the credentials are set. The method might look like the one below: public void ConfigureProxy(ClientBase<Object> proxy) {     proxy.ClientCredentials.UserName.UserName = "u";     proxy.ClientCredentials.UserName.Password = "p"; } Unfortunately we can't pass to that method a proxy of type ClientBase<IMyContract> because of nonvariant nature of C# generics. I can see at least two options how to get around that issue. The first one requires you to clutter the method with a generic parameter despite the fact that there is no use of it.

public void ConfigureProxy <T>(ClientBase <T> proxy) where T : class   
{
proxy.ClientCredentials.UserName.UserName = "u";
proxy.ClientCredentials.UserName.Password = "p";
}
You can imagine I'm not big fun of this solution. The second one is based on the idea that the non-generic part of the public interface of ClientBase class is exposed as either a non-generic ClientBase class or a non-generic interface IClientBase. Approach based on a non-generic class:

public abstract class ClientBase : ICommunicationObject, IDisposable   
{
public ClientCredentials ClientCredentials
{
//some code goes here
}
}

public abstract class ClientBase <T> : ClientBase where T : class
{
}

Approach based on a non-generic interface:

public interface IClientBase : ICommunicationObject, IDisposable 
{
ClientCredentials ClientCredentials { get; }
}

public abstract class ClientBase <T> : IClientBase where T : class
{
}

Having that hierarchy in place we could define our method in the following way:


public void ConfigureProxy(ClientBase/IClientBase proxy)
{
proxy.ClientCredentials.UserName.UserName = "u";
proxy.ClientCredentials.UserName.Password = "p";
}

Unfortunately WCF architects haven't thought about that and a non-generic ClientBase/IClientBase class/interface doesn't exist. The interesting part of this story is that the FaultException<T> class does not suffer from the same problem because there is a non-generic FaultException class that exposes all the non-generic members. The FaultException<T> class basically adds a single property that returns the detail of the fault and that's it. I can find more classes that are implemented in exactly the same way FaultException<T> is implemented. It looks like ClientBase<T> is the only one widely used class that breaks that rule. I would love to see this inconvenience fixed as an extension of C# parameter variance.

Monday, 12 November 2007

Irish Java Technology Conference launch from .NET engineer perspective

After the Joel Spolsky presentation that launched IJTC there was a panel discussion which meant to explore all the future directions that Java as a platform might take. The participants were talking about the future in a kind of sad way and the discussion toured out to be mainly a never-ending stream of complaints. Basically people were concerned about:
  • Java 6 is not implemented on Leopard
  • mobile phone specs on the vendors web sites don't list Java as a feature, something like Java ready sticker
  • lack of tools
  • diversity of frameworks and their life-span uncertainty
  • growing complexity of the language itself
  • dynamic languages that from their perspective are taking over Java current and future believers
  • etc.
One of the listeners asked how to anticipate the life-span of a given framework. The answer was that it's impossible, that's fine, and that his company needs to be more agile. Excuse me? If you build a house you don't want to change its foundation too often. As far as I know Microsoft provides 10 years of support for every framework they release. The next interesting statement was that Java is developing itself quickly because it's community driven. I think that this is not true and the best example is C#. The first version of it was way behind Java at that time it was released. Nowadays C# is way ahead of Java and the main reason is that there are a few smart guys at Microsoft who listen to developers but at the same time they are able to make quick decisions when it's needed. I love diversity but it looks like Java is going in so many different directions that even its believers are kind of lost. What is more, exploring (too)many directions at the same time always affects your velocity and you always have to find the right balance. I can not recall a single statement which would mention a framework/solution/approach which is a breakthrough and it will make the developers life much easier.
I might be wrong because I don't follow the Java world on daily basis but my overall impression was that both audience and guests were not really happy what they came up with. But there is a good chance that they weren't actually upset but simply tired :) because of the fact that the discussion finished around 10 pm. I hope that a few pints after the launch let them recharge the batteries because the conference itself looks interesting.

Friday, 20 July 2007

Dynamic nature of C# I bet you don't know :)

Yesterday I read a blog post that meant to discuss possible naming conventions for LINQ but it turned out that the most interesting part of it was something completely different. Namely, Krzysztof Cwalina wrote that we don't have to implement IEnumerable and IEnumerator to be able to iterate through an object(collection) using foreach statement. It's enough that a class exposes GetEnumerator() method. It doesn't have to implement IEnumerable interface. At the beginning I thought that it's just another example of syntactic sugar and that the C# compiler generates implicit IEnumerable declaration on our behalf. But then I opened ildasm.exe and saw that that's not the case. IEnumerable wasn't there. That's it. Have a look at the code snippet and screen shot below to check it out.
The bottom line is that I learn every day and .NET doesn't stop surprising me which is fun :).
EDIT: I've modified the image because it looked horrible.

using System;
using System.Collections.Generic;
using System.Text;
using System.Collections;
class Program
{
    static void Main(string[] args)
    {
        FakeEnumerableClass enumerable = new FakeEnumerableClass();

        foreach (object o in enumerable)
        {

            //works perfectly fine :)
        }
    }
}
class FakeEnumerableClass
{
    public FakeEnumerator GetEnumerator()
    {
        return new FakeEnumerator();
    }
}
public class FakeEnumerator
{
    public bool MoveNext()
    {
        return false;
    }

    public object Current
    {
        get
        {
            return null;
        }
    }
}
class RealEnumberableClass : IEnumerable
{
    public IEnumerator GetEnumerator()
    {
        throw new Exception("The method or operation is not implemented.");
    }
}


 

Sunday, 8 July 2007

Great book: C# via CLR

As I mentioned earlier I always wanted to read C# via CLR by Jeffrey Richter. Finally I got it a few months ago and while I was sick I read it. I think it's just brilliant because:
  • I like the way Jeffery explains problems.He is strict and precise whenever it's needed but no more.
  • As far as I know he is not a Microsoft employee which lets him express criticism of everything that deserves it.
  • It reveals lots of things that you will never be aware of unless you start thinking in an illogical way. Unfortunately CLR and/or C# not always behave in a predictable way.
  • The books touches nearly all the .NET internals that you can come across during your everyday job as long as you don't work on compilers and runtimes :).

Saturday, 26 May 2007

How to pollute C#

You can call me a purist but from my point of view the most valuable feature of C# is its consistency and explicitness. It seems that there are 2 teams at Microsoft that work on C#. One of them introduces great features like LINQ but the second one seems to support laziness of any kind and keeps introducing features that may(will) confuse software developers. Unfortunately it looks like the 'bad' team is not going to stop its activity. Their last idea which is called partial methods and is dedicated to code generator vendors smells like a C/C++ concept. Why? Because a partial method consist of method declaration(C++ header file) and method implementation(C++ cpp file). If you don't provide an implementation then the C# compiler will remove all calls to that method from your code! This means that your C# code that sits in a.cs file doesn't correspond to the C# code compiler sends to MSIL generator. Maybe it's me but I am not mad about at least half of the features Microsoft ships with Orcas(.NET 3.5).