The Inquisitive Coder – Davy Brion's Blog

Trying to walk that thin line between intelligence and ignorance

Archive for the 'Silverlight' Category

What Business Applications Could (Or Should) Look Like

Posted by Davy Brion on 3rd January 2010

A lot of us develop business applications, right? Ever got tired of the same old boring and traditional user interfaces that are used for these applications?  At Item Solutions we like to do things differently from what other companies are doing, and we apply that principle to our user interfaces as well.  One of my coworkers recently created a couple of screencasts of some of our Silverlight applications and i figured you might find them interesting.  You’ll see that in most cases, the way the data is presented isn’t quite how most applications do it, and the way you interact with the data is often different as well.  Not only is this more interesting to work on, most users actually love the user experience that these interfaces offer them.

Check out the movies, and if you want a bit more information on what these applications do, just click here.

CRM from itemsolutions on Vimeo.

Genesis from itemsolutions on Vimeo.

Glance from itemsolutions on Vimeo.

Emmaus from itemsolutions on Vimeo.

Synergy from itemsolutions on Vimeo.

Nokeos from itemsolutions on Vimeo.

Posted in Opinions, Silverlight | No Comments »

Unit Tests And Silverlight

Posted by Davy Brion on 16th December 2009

Capture

This is something that Steven De Kock and Tom Ceulemans (two coworkers of mine without a blog, so no link) have been working on.  Those are Silverlight tests, executing in the Silverlight runtime, within a full browser context.

And yes, they will release it as an open source project soon :)

Posted in Silverlight, Test Driven Development | 8 Comments »

Integrated Security With Silverlight And WCF

Posted by Davy Brion on 3rd November 2009

I lost some time yesterday trying to get a Silverlight client to use Integrated Security with a WCF service so i figured i’d post the steps necessary to make it work here.

First of all, you need to make sure that your IIS installation has support for Windows Authentication. Go to Add/Remove Programs (appwiz.cpl), click on Turn Windows Features on or off, select Internet Information Services – World Wide Web Services – Security and make sure that Windows Authentication is checked.

Next, you need to make sure that the virtual directory where you’re hosting the WCF service has Windows Authentication enabled. Open Internet Information Services Manager (inetmgr), select the virtual directory where the WCF service is hosted, click on the Authentication icon and enable Windows Authentication.

After that, you need to add the following to the binding configuration of the service endpoint (in the host, obviously):

          <security mode="TransportCredentialOnly">

            <transport clientCredentialType="Windows" />

          </security>

I only got it working with basicHttpBinding, so unfortunately i can no longer use the customBinding to use binary XML…

In your Silverlight project, open the ServiceReferences.ClientConfig file and add the following to the binding configuration:

          <security mode="TransportCredentialOnly" />

After that, you should be able to do this in your WCF service:

            WindowsIdentity myuser = ServiceSecurityContext.Current.WindowsIdentity;

And that should return the Windows user of the user running the Silverlight client.

For the record: this is with Silverlight 3… i have no idea if it’ll work with Silverlight 2

Posted in Silverlight, WCF | 1 Comment »

Event Aggregation

Posted by Davy Brion on 9th October 2009

We’re experimenting at work with a bit of a different approach as to how we structure our views and how they will interact with each other. We already know that our views will be reused in many different contexts so having them communicate with other views is something that needs to be done in a very loosely coupled manner. I don’t want any of the views to even know about the existence of other views, let alone having them know about specific instances of them.

But these views do have to interact with each other. I didn’t want to use typical events because that would require either a certain view to know about another view to be able to subscribe to its events, or you’d need some other component which knows which views need to be hooked to each other. We really need maximum flexibility for what we have in mind with our views, so it only made sense to finally start using the Event Aggregation pattern. The idea is that a view can basically publish events, without knowing who is subscribed to these events, and that suscribers will be notified whenever these events occur. However, subscribers don’t know anything about who is publishing the events. Instead, both publishers and subscribers only know of the Event Aggregator. A publisher tells the aggregator to publish an event to all subscribed listeners for that event. Each subscribers simply tells the aggregator “i’d like to be notified whenever this event occurs, and i don’t care where it comes from”.
Plenty of implementations of this pattern can be found online already, so i figured: why not add my own? :p

Fist of all, an event is nothing more than a class that inherits from this class:

    public abstract class Event {}

Every event should inherit from this class, and add whatever necessary properties that are important for that particular type of event.

If a class is interested in listening to a specific event, it needs to implement the following interface:

    public interface IListener { }

 

    public interface IListener<TEvent> : IListener

        where TEvent : Event

    {

        void Handle(TEvent receivedEvent);

    }

If a class is interested in multiple events, it simply needs to implement the generic IListener interface for each type of event that it wants to handle.

Then we obviously need the Event Aggregator. I wanted an aggregator that allowed listeners to either subscribe/unsubscribe to/from very specific events, or just subscribe/unsubscribe to/from whatever it supports. So i have the following IEventAggregator interface:

    public interface IEventAggregator

    {

        void Publish<TEvent>(TEvent message) where TEvent : Event;

        void Publish<TEvent>() where TEvent : Event, new();

 

        void Subscribe(IListener listener);

        void Unsubscribe(IListener listener);

 

        void Subscribe<TEvent>(IListener<TEvent> listener) where TEvent : Event;

        void Unsubscribe<TEvent>(IListener<TEvent> listener) where TEvent : Event;

    }

The Subscribe and Unsubscribe methods that simply take an IListener reference will either subscribe or unsubscribe the given listener to/from every event that it can handle. In other words, for every generic IListener interface that it implements. Yet you also have the ability to subscribe/unsubscribe from a specific event type.

And here’s the implementation:

    public class EventAggregator : IEventAggregator

    {

        private readonly object listenerLock = new object();

        protected readonly Dictionary<Type, List<IListener>> listeners = new Dictionary<Type, List<IListener>>();

        private readonly IDispatcher dispatcher;

 

        public EventAggregator(IDispatcher dispatcher)

        {

            this.dispatcher = dispatcher;

        }

 

        public virtual void Subscribe(IListener listener)

        {

            ForEachListenerInterfaceImplementedBy(listener, Subscribe);

        }

 

        public virtual void Unsubscribe(IListener listener)

        {

            ForEachListenerInterfaceImplementedBy(listener, Unsubscribe);

        }

 

        private static void ForEachListenerInterfaceImplementedBy(IListener listener, Action<Type, IListener> action)

        {

            var listenerTypeName = typeof(IListener).Name;

 

            foreach (var interfaceType in listener.GetType().GetInterfaces().Where(i => i.Name.StartsWith(listenerTypeName)))

            {

                Type typeOfEvent = GetEventType(interfaceType);

 

                if (typeOfEvent != null)

                {

                    action(typeOfEvent, listener);

                }

            }

        }

 

        private static Type GetEventType(Type type)

        {

            if (type.GetGenericArguments().Count() > 0)

            {

                return type.GetGenericArguments()[0];

            }

 

            return null;

        }

 

        public virtual void Subscribe<TEvent>(IListener<TEvent> listener) where TEvent : Event

        {

            Subscribe(typeof(TEvent), listener);

        }

 

        protected virtual void Subscribe(Type typeOfEvent, IListener listener)

        {

            lock (listenerLock)

            {

                if (!listeners.ContainsKey(typeOfEvent))

                {

                    listeners.Add(typeOfEvent, new List<IListener>());

                }

 

                if (listeners[typeOfEvent].Contains(listener))

                {

                    throw new InvalidOperationException("You're not supposed to register to the same event twice");

                }

 

                listeners[typeOfEvent].Add(listener);

            }

        }

 

        public virtual void Unsubscribe<TEvent>(IListener<TEvent> listener) where TEvent : Event

        {

            Unsubscribe(typeof(TEvent), listener);

        }

 

        protected virtual void Unsubscribe(Type typeOfEvent, IListener listener)

        {

            lock(listenerLock)

            {

                if (listeners.ContainsKey(typeOfEvent))

                {

                    listeners[typeOfEvent].Remove(listener);

                }

            }

        }

 

        public virtual void Publish<TEvent>(TEvent message) where TEvent : Event

        {

            var typeOfEvent = typeof(TEvent);

 

            lock (listenerLock)

            {

                if (!listeners.ContainsKey(typeOfEvent)) return;

 

                foreach (var listener in listeners[typeOfEvent])

                {

                    var typedReference = (IListener<TEvent>)listener;

                    dispatcher.BeginInvoke(() => typedReference.Handle(message));

                }

            }

        }

 

        public virtual void Publish<TEvent>() where TEvent : Event, new()

        {

            Publish(new TEvent());

        }

    }

In case you’re wondering… the IDispatcher interface is merely a way to wrap Silverlight’s real Dispatcher. We wrap it so we can use a different implementation of the IDispatcher in our automated tests. Other than that, the implementation is very straightforward.

We started using this very recently, so this implementation might change in the upcoming weeks, but for now it does what it needs to do and it does so pretty well. In our case, every view’s Presenter automatically has an IEventAggregator property so whenever we need to publish an event, we can simply do something like EventAggregator.Publish(new SomeEvent(someParameter)). Or, Presenters that need to listen to events can simply say EventAggregator.Subscribe(this) or only subscribe to some specific events whenever they need to and their specific Handle method will be called whenever someone publishes the event. This also allowed us to get rid of the somewhat awkward syntax when testing events (subscription, unsubscription and the actual handing of events) with mocking frameworks.

And as a last bonus, i put a call to the Unsubscribe(IListener) method in the Dispose method of our base Presenter implementation. Which means that none of them will be left subscribed to events by accident anymore :)

Posted in Patterns, Silverlight | 6 Comments »

5 Reasons Why Silverlight Is My Preferred Web Development Platform

Posted by Davy Brion on 5th September 2009

Item Solutions (where i work) has been using Silverlight ever since the first version came out, and by now we have quite a bit of experience and dare i say expertise in it. We generally suggest using Silverlight for every new project that we do, and the only time we don’t use it is when customers don’t want us to use it. This happens very rarely though.

While i generally don’t get involved in most of the UI stuff, i’m pretty happy with this because i seriously like Silverlight as a platform. Below is my list of top 5 reasons why Silverlight is my preferred platform for Web Development nowadays:

  1. The ability to create an excellent UIX which definitely matters to customers.

    We have some projects at work where the Silverlight UI definitely receives a “wow” response from customers. Not only because the UI is extremely responsive and snappy, but also because we can use new ways of visualizing data and enabling user actions in the UI in ways that are either completely new for web applications, or just new in general. We can easily create much more intuitive user interfaces with a responsiveness that can easily compete with that of desktop applications.

  2. Low bandwidth overhead

    Downloading the XAP file can sometimes be painfully slow, depending on your bandwidth obviously, but once it’s downloaded it’s also cached by the user’s browser. Everything that happens after that consumes very little bandwidth. There is no CSS, no HTML markup, no javascript, … the only thing that goes over the wire is the data that you actually need. And with Silverlight’s Binary XML feature you’re also using less bandwidth than before. This might not seem like a big deal to you, but bandwidth has a huge impact on the client-side responsiveness as well as your server-side ability to process requests.

  3. The client is stateful again

    This one is huge to me. We don’t have to deal with things like ViewState or SessionState or anything like that. If a client has retrieved a set of data, it can just keep it in memory if it makes sense to do so. This is especially useful for things like user-profiles, or static data that never changes but it has an impact on pretty much everything you develop. You can simply keep whatever data you need in memory, and it has no impact on the server at all. Well, it actually reduces the amount of data that you need to send to the server (or receive), and the number of requests you need the server to handle to implement the functionality you need client-side. This is pretty much a win-win for both the client and the server whereas with typical ASP.NET development, either the client or the server has to take some kind of a hit when it comes to maintaining state (even if it’s only a little).

  4. The ability to write the client almost entirely in C#

    I don’t know about you, but my HTML, CSS and Javascript skills are extremely limited. This seriously reduces my effectiveness when i need to make changes in the presentation layer in typical ASP.NET applications. And while my XAML skills aren’t what they should be, my C# skills are sufficient for me to be effective in client-side changes. I can easily look at a piece of client-side code and make whatever change i need to make without having to consult a reference guide. That’s not the biggest advantage to being able to write the client in C# though. Existing C# skills are very easily transferable to the Silverlight side of things, which means that a larger pool of developers is available to work on your front-end. True, there is a bit of a learning curve when it comes to Silverlight, but i’d argue that there is a much steeper learning curve to doing traditional client-side web development effectively.

  5. It’s only going to get better

    As much as i like Silverlight, it is by no means perfect and there is plenty of room for improvement. That’s normal though for such a young platform. In the future we’ll see plenty of new libraries and tools that will become available to Silverlight developers which should enable us to create even better web applications. Microsoft is investing a lot of money and effort into it, and i’m pretty sure that others will follow.

Now, you won’t hear me say that Silverlight is the perfect solution for every web application. SEO is still a problem, as well as acceptance of the Silverlight plugin in corporate environments (though this will only improve over time). But, in the situations where you can use Silverlight, it certainly pays off to do so.

Posted in Opinions, Silverlight | 15 Comments »

Finding Memory Leaks In Silverlight With WinDbg

Posted by Davy Brion on 8th August 2009

As i mentioned in a previous post, you can attach WinDbg to a browser to find memory leaks in your Silverlight applications. I figured it would be a good idea to write down how this process works, since i always end up having to look it up again whenever i need to do this.

I wrote a very simple Silverlight application which has a rather typical memory leak. Here’s the actual code:

        public event EventHandler<MyEventArgs> MyEvent = delegate { };

 

        private void CreateNewViewButton_OnClick(object sender, RoutedEventArgs e)

        {

            ViewContainer.Children.Clear();

 

            var newView = new MyView();

            MyEvent += newView.EventHandler;

 

            ViewContainer.Children.Add(newView);

        }

For some of you, the memory leak is already very clear. Like i said, it’s a very simple example ;)

Let’s go through the process of finding and fixing the memory leak using WinDbg. First of all, download Debugging Tools For Windows (which contains the WinDbg executable) here and install it.

Then we start our application in Internet Explorer (for some reason i can’t use WinDbg to inspect the managed memory heap with Firefox, so i just use Internet Explorer for this stuff) and use it. In the case of my example, that means clicking the button which creates a new view a couple of times.

Open WinDbg.exe and select the ‘Attach to a Process’ menu item in the ‘File’ menu and select the iexplore.exe process.

Then you need to load the correct version of sos.dll:

step1

After that we can see which types of our MySilverlightApplication namespace are present in the managed heap, including how many instances of them:

step2

As you can see, there are 13 instances of our MyView type present in the heap. Using the value in the MT column, we can drill down further:

step3

This shows the memory address of each instance of the MyView type in the heap. Now we can see if there are any live references to these instances:

step4

This is actually for the first address that was listed. As you can see, it is still a reachable reference, which means it will not be collected by the garbage collector. The chain of references clearly indicates that the instance is still referenced from our event in the MainPage instance. All of the previously listed instances show the same reference chain, so this is clearly a memory leak. Even though we should only have one active reference of MyView at any point in time of this application, the MyEvent event on MainPage clearly keeps each instance of MyView alive.

The correct way to fix this is to make sure that whenever we remove an instance of MyView, we need to unsubscribe it from the MainPage’s MyEvent handler. Always remember this rule when it comes to dealing with events: if the publisher of the event has a longer lifetime than the subscriber of the event, then you absolutely have to unsubscribe each subscriber from the event or the publisher will keep references to each subscriber (preventing them from being garbage collected) for as long as the publisher is alive.

Here’s the modified version of the above code which avoids the memory leak:

        public event EventHandler<MyEventArgs> MyEvent = delegate { };

 

        private void CreateNewViewButton_OnClick(object sender, RoutedEventArgs e)

        {

            CleanUpPreviousView();

 

            var newView = new MyView();

            MyEvent += newView.EventHandler;

 

            ViewContainer.Children.Add(newView);

        }

 

        private void CleanUpPreviousView()

        {

            if (ViewContainer.Children.Count > 0)

            {

                var myView = ViewContainer.Children[0] as MyView;

                if (myView != null) MyEvent -= myView.EventHandler;

                ViewContainer.Children.Clear();

            }

        }

Let’s see if this really fixed the memory leak. If we fire up the application and press the button a couple of times, the application should normally only have one live reference of MyView in memory.

step5

I clicked the button 5 times, and the above output shows that there are 5 instances of MyView on the heap. So did we fix the leak or not? Check the output below:

step6

As you can see, only the last instance of MyView is actively referenced somewhere. That means that the first 4 instances are ready to be collected during the next garbage collection.

One thing i don’t understand though, is that the reference chain of the last instance doesn’t mention MainPage or the event handler anymore. But when i attached Visual Studio’s debugger to the browser instance i could clearly see that the MyEvent of MainPage indeed contained an event handler that pointed to this MyView instance. I’m far from a WinDbg and SOS expert so i have no idea why the reference chain doesn’t reflect this. Perhaps someone with more WinDbg and SOS knowledge can shed some light on this?

Either way, this approach is a pretty good way of finding memory leaks in your Silverlight code. In a real application it’s obviously a bit more complicated to find the exact cause of a leak compared to this simple example, but it’s still pretty doable. Just execute the !dumpheap -stat -type YourRootNameSpaceHere and look for unusually high numbers of instances of your types. Then you can start looking at each instance to figure out what’s going on. And for a nice list of commands that you can execute in WinDbg with SOS, be sure to check this out.

Also, keep in mind that you can do this for every .NET process, and not just Silverlight. Though you would need to load the sos.dll file of your particular .NET version.

Posted in Memory Management, Silverlight | 8 Comments »

Refactor Safe Implementation Of INotifyPropertyChanged

Posted by Davy Brion on 5th August 2009

One thing that always annoyed the hell out of me when implementing INotifyPropertyChanged for Silverlight (or WPF) databinding was the fact that you have to provide the name of the property as a string. There are some cool AOP solutions to this, but if you can’t use those for whatever reason, you could use LINQ’s Expressions to avoid having to use strings.

We already have a base PresentationModel which has the following method:

        protected void NotifyPropertyChanged(string propertyName)

        {

            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));

        }

We also have a generic PresentationModel class which inherits from this class:

    public abstract class PresentationModel<TPresentationModel> : PresentationModel

        where TPresentationModel : PresentationModel<TPresentationModel>

    {

        protected void NotifyPropertyChanged(Expression<Func<TPresentationModel, object>> expression)

        {

            var memberExpression = expression.Body as MemberExpression;

 

            if (memberExpression == null)

            {

                throw new InvalidOperationException("You must specify a property!");

            }

 

            NotifyPropertyChanged(memberExpression.Member.Name);

        }

    }

Notice that you pass an expression to the NotifyPropertyChanged method. It can be used like this:

    public class MyTestPresentationModel : PresentationModel<MyTestPresentationModel>

    {

        private string myString;

 

        public string MyString

        {

            get

            {

                return myString;

            }

            set

            {

                myString = value;

                NotifyPropertyChanged(t => t.MyString);

            }

        }

    }

That’s pretty cool, but you should be able to test this easily, right? That’s pretty easy to do as well:

    public class PresentationModelTest<TPresentationModel> where TPresentationModel : PresentationModel<TPresentationModel>

    {

        protected void AssertThatPropertyChangedIsCorrect<TArgument>(TPresentationModel model,

            Expression<Func<TPresentationModel, TArgument>> property, TArgument value)

        {

            var memberInfo = ((MemberExpression)property.Body).Member;

            var propertyName = memberInfo.Name;

 

            bool eventProperlyTriggered = false;

            model.PropertyChanged += (s, e) => eventProperlyTriggered = e.PropertyName.Equals(propertyName);

            typeof(TPresentationModel).GetProperty(propertyName).SetValue(model, value, null);

 

            Assert.IsTrue(eventProperlyTriggered);

        }

    }

 

    [TestClass]

    public class PresentationModelTests : PresentationModelTest<MyTestPresentationModel>

    {

        [TestMethod]

        public void NotifyPropertyChanged_WithExpression_TriggersCorrectPropertyChangedEvent()

        {

            var model = new MyTestPresentationModel();

            AssertThatPropertyChangedIsCorrect(model, m => m.MyString, "blah");

        }

    }

There we go… no more strings so refactoring won’t break anything, and it’s easy to test as well.

Posted in Silverlight | 7 Comments »

Tracking Dangling Object References In Silverlight

Posted by Davy Brion on 4th August 2009

One of the downsides of working with a young platform like Silverlight is that the tool support isn’t quite ‘there’ yet, particularly when it comes to profiling for performance and memory usage. And as you may or may not know, Silverlight makes it very easy to introduce memory leaks into your code. Since you can’t just attach a memory profiler to your Silverlight application, optimizing memory usage or tracking down a leak can be a real pain in the ass.

In the past i have resorted to grabbing a memory dump of the browser and analyzing the content of the managed heap with windbg to track down which instances where being kept in memory. While this works, it’s pretty time consuming and can quite easily lead you down the wrong path. One of the most important things that you want to know in this specific case is: which types are being kept in memory, and how many of them?

In this case, being able to query something during debugging regarding which instances are still kept alive in memory at certain times is sufficient for me. So i came up with the following class:

    public static class ObjectTracker

    {

        private static readonly object monitor = new object();

        private static readonly List<WeakReference> objects = new List<WeakReference>();

        private static bool? shouldTrack;

 

        public static void Track(object objectToTrack)

        {

            if (ShouldTrack())

            {

                lock (monitor)

                {

                    objects.Add(new WeakReference(objectToTrack));

                }

            }  

        }

 

        private static bool ShouldTrack()

        {

            if (shouldTrack == null)

            {

                shouldTrack = Debugger.IsAttached;

            }

 

            return shouldTrack.Value;

        }

 

        public static IEnumerable<object> GetAllLiveTrackedObjects()

        {

            lock (monitor)

            {

                GC.Collect();

                return objects.Where(o => o.IsAlive).Select(o => o.Target);

            }

        }

    }

The idea is basically to just keep a list of WeakReferences of objects you want to track (only if a debugger is attached), and later on you can ‘query’ the live instances through the GetAllLiveTrackedObjects method. This method obviously performs a full garbage collect to make sure only objects that are really still alive are returned. Again, you should almost never do a GC.Collect() manually, but in this case the method will only be called while you’re debugging.

Then, you strategically put the following line in the constructor of every kind of type you’d like to track:

            ObjectTracker.Track(this);

I have that line in the constructor of my base View class, my base Controller class and in my base Disposable class. So now, when i want to check if there are any dangling references to instances of types that i really don’t want hanging around, i can just do something like this:

            var liveObjects = ObjectTracker.GetAllLiveTrackedObjects();

 

            if (Debugger.IsAttached)

            {

                Debugger.Break();

            }

And then manually inspect the content of the liveObjects collection. It’s far from perfect, but at least it’s an easy way to at least know which instances (that i care about) are being kept in memory. It’ll do until we get better tool support :p

Posted in Memory Management, Silverlight | 4 Comments »

Hosting Silverlight Client Apps In A Silverlight Host App

Posted by Davy Brion on 2nd August 2009

For one of our customers, we need to be able to host multiple Silverlight applications within one dedicated Silverlight ‘host’ application. Prism offers this ability, but we already have our own implementations for pretty much all of the other stuff that Prism offers (and that we need), so we figured we might as well implement this hosting feature ourselves. It turns out it’s pretty easy to do this.

The general idea is to be able to implement each client application in its own Silverlight Application Project, and to have the ability to download each client aplication’s XAP file into the Host application and display it within the designated visual area for the currently active client application.

First, we need an interface that each client application needs to contain an implementation of:

    public interface IClientApplication

    {

        void Initialize();

        void Cleanup();

 

        UIElement VisualContainer { get; }

    }

The VisualContainer property needs to return a UIElement which is basically the main visual container element of the client application. This could be its main page or just a grid or just about any graphical component.

Then we need a class to download XAP files based on their URI. Since you have to do all of these things asynchronously in Silverlight, and the generally used approach seems to be the event-based async pattern, i use the following base eventargs class for all of my asynchronous operations:

    public abstract class AsyncOperationCompletedEventArgs<T> : EventArgs

    {

        protected AsyncOperationCompletedEventArgs(T result, Exception error)

        {

            this.result = result;

            Error = error;

        }

 

        public Exception Error { get; set; }

 

        private readonly T result;

 

        public T Result

        {

            get

            {

                if (Error != null)

                {

                    throw new InvalidOperationException("The operation did not complete succesfully, please retrieve the Error property");

                }

 

                return result;

            }

        }

    }

And then we have the DownloadCompletedEventArgs class:

    public class DownloadCompletedEventArgs : AsyncOperationCompletedEventArgs<Stream>

    {

        public DownloadCompletedEventArgs(Stream result, Exception e) : base(result, e) {}

    }

Now we can write our simple FileDownloader class:

    public interface IFileDownloader

    {

        event EventHandler<ProgressChangedEventArgs> ProgressChanged;

        event EventHandler<DownloadCompletedEventArgs> DownloadCompleted;

        void StartDownloading(Uri locationOfResource);

    }

 

    public class FileDownloader : IFileDownloader

    {

        public event EventHandler<ProgressChangedEventArgs> ProgressChanged = delegate { };

        public event EventHandler<DownloadCompletedEventArgs> DownloadCompleted = delegate { };

 

        public void StartDownloading(Uri locationOfResource)

        {

            var webClient = new WebClient();

            webClient.DownloadProgressChanged += webClient_DownloadProgressChanged;

            webClient.OpenReadCompleted += webClient_OpenReadCompleted;

            webClient.OpenReadAsync(locationOfResource);

        }

 

        private void webClient_OpenReadCompleted(object sender, OpenReadCompletedEventArgs e)

        {

            DownloadCompletedEventArgs eventArgs;

 

            if (!e.Cancelled && e.Error == null)

            {

                eventArgs = new DownloadCompletedEventArgs(e.Result, null);

            }

            else

            {

                eventArgs = new DownloadCompletedEventArgs(null, e.Error);

            }

 

            DownloadCompleted(this, eventArgs);

        }

 

        private void webClient_DownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e)

        {

            ProgressChanged(this, new ProgressChangedEventArgs(e.ProgressPercentage, null));

        }

    }

We also need something to extract the assemblies from a downloaded XAP file:

    public interface IXapReader

    {

        IEnumerable<Assembly> GetAssemblies(Stream stream);

    }

 

    public class XapReader : IXapReader

    {

        public IEnumerable<Assembly> GetAssemblies(Stream stream)

        {

            var assemblies = new List<Assembly>();

 

            foreach (var deploymentPart in GetDeploymentParts(stream))

            {

                assemblies.Add(LoadAssembly(deploymentPart, stream));

            }

 

            return assemblies;

        }

 

        private static Assembly LoadAssembly(XElement deploymentPart, Stream stream)

        {

            var assemblyPart = new AssemblyPart();

            var source = deploymentPart.Attribute("Source").Value;

 

            var streamResourceInfo = Application.GetResourceStream(

                new StreamResourceInfo(stream, "application/binary"),

                new Uri(source, UriKind.Relative));

 

            return assemblyPart.Load(streamResourceInfo.Stream);

        }

 

        private static IEnumerable<XElement> GetDeploymentParts(Stream stream)

        {

            var appManifest = GetApplicationManifest(stream);

            var deploymentRoot = XDocument.Parse(appManifest).Root;

            return deploymentRoot.Elements().First().Elements();

        }

 

        private static string GetApplicationManifest(Stream stream)

        {

            return new StreamReader(Application.GetResourceStream(

                new StreamResourceInfo(stream, null),

                new Uri("AppManifest.xaml", UriKind.Relative)).Stream)

                .ReadToEnd();

        }

    }

And then we can write a class which can retrieve the type which implements the IClientApplication interface from a downloaded XAP file:

    public interface IClientApplicationTypeLoader

    {

        event EventHandler<ClientApplicationLoadedEventArgs> LoadCompleted;

        event EventHandler<ProgressChangedEventArgs> ProgressChanged;

        void Load(Uri xapLocation);

    }

 

    public class ClientApplicationTypeLoader : IClientApplicationTypeLoader

    {

        public event EventHandler<ClientApplicationLoadedEventArgs> LoadCompleted = delegate { };

        public event EventHandler<ProgressChangedEventArgs> ProgressChanged = delegate { };

 

        private IFileDownloader fileDownloader;

        private IXapReader xapReader;

 

        public ClientApplicationTypeLoader(IFileDownloader fileDownloader, IXapReader xapReader)

        {

            this.fileDownloader = fileDownloader;

            this.xapReader = xapReader;

 

            fileDownloader.ProgressChanged += downloader_ProgressChanged;

            fileDownloader.DownloadCompleted += downloader_DownloadCompleted;

        }

 

        public void Load(Uri xapLocation)

        {

            fileDownloader.StartDownloading(xapLocation);

        }

 

        private void downloader_ProgressChanged(object sender, ProgressChangedEventArgs e)

        {

            ProgressChanged(this, e);

        }

 

        private void downloader_DownloadCompleted(object sender, DownloadCompletedEventArgs e)

        {

            if (e.Error != null)

            {

                LoadCompleted(this, new ClientApplicationLoadedEventArgs(null, e.Error));

                return;

            }

 

            var assemblies = xapReader.GetAssemblies(e.Result);

            var clientApplicationType = FindClientApplicationType(assemblies);

            LoadCompleted(this, new ClientApplicationLoadedEventArgs(clientApplicationType, null));

        }

 

        private Type FindClientApplicationType(IEnumerable<Assembly> assemblies)

        {

            foreach (var assembly in assemblies)

            {

                foreach (var type in assembly.GetTypes())

                {

                    if (type.GetInterfaces().Contains(typeof(IClientApplication)))

                    {

                        return type;

                    }

                }

            }

 

            return null;

        }

    }

Obviously, this code doesn’t deal with the possibility of multiple or no IClientApplication implementations within the same XAP file. Not really relevant for this post though ;)

And now, we can simply do something like this within our host application:

            clientApplicationTypeLoader.LoadCompleted += loader_LoadCompleted;

            clientApplicationTypeLoader.ProgressChanged += loader_ProgressChanged;

            clientApplicationTypeLoader.Load(xapUri);

and the LoadCompleted event handler could look like this:

        void loader_LoadCompleted(object sender, ClientApplicationLoadedEventArgs e)

        {

            if (e.Error != null)

            {

                throw new Exception("error while retrieving client application", e.Error);

            }

 

            CleanupCurrentClientApp();

 

            var clientApp = (IClientApplication)Activator.CreateInstance(e.Result);

            clientApp.Initialize();

 

            AppContainer.Children.Add(clientApp.VisualContainer);

        }

 

        private void CleanupCurrentClientApp()

        {

            if (AppContainer.Children.Count == 0)

            {

                return;

            }

 

            var currentClientApp = (IClientApplication)AppContainer.Children[0];

            currentClientApp.Cleanup();

 

            AppContainer.Children.Clear();

        }

And that’s all there is to it.

Update: download a sample of this here.

Posted in Silverlight | 4 Comments »

Silverlight Localization Gotcha

Posted by Davy Brion on 27th March 2009

Wasted a bit of time figuring this out, so i’m posting it here for future reference. We have this multi-language silverlight app where the UI needs to be shown in either English or Dutch. So you know, i copied my TextResources.resx file (which contains the translated strings in English) and created a TextResources.nl.resx file where i replaced the English strings with the Dutch strings.

In the output folder of the Silverlight project, you can clearly see that the Our.KickAss.Silverlight.Project.resources.dll file is located in the ‘nl’ folder. The XAP file that is being copied to the actual web project however, doesn’t contain the dutch resources.

Apparantly, the key to ‘fixing’ this is opening the .csproj file of your Silverlight project, and then you need to modify the SupportedCultures element so it contains the cultures you’re supporting:

<SupportedCultures>en;nl</SupportedCultures>

There might be a way to do this from the UI within Visual Studio, but i sure didn’t find it anywhere.

And now you can simply switch between the translations setting the generated resource class’s static Culture property to the culture you want, for instance:

            TextResources.Culture = new CultureInfo("nl-BE");

Posted in Silverlight | 2 Comments »