<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:openSearch="http://a9.com/-/spec/opensearch/1.1/" xmlns:georss="http://www.georss.org/georss" xmlns:gd="http://schemas.google.com/g/2005" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" gd:etag="W/&quot;DUEASHk8fSp7ImA9WxBaEkg.&quot;"><id>tag:blogger.com,1999:blog-8944256652433533647</id><updated>2010-03-22T07:34:09.775-04:00</updated><title>C#er : IMage</title><subtitle type="html">C# and .NET solutions: Silverlight, NHibernate, JavaScript, AJAX, Unity, and more.</subtitle><link rel="http://schemas.google.com/g/2005#feed" type="application/atom+xml" href="http://csharperimage.jeremylikness.com/feeds/posts/default" /><link rel="alternate" type="text/html" href="http://csharperimage.jeremylikness.com/" /><link rel="next" type="application/atom+xml" href="http://www.blogger.com/feeds/8944256652433533647/posts/default?start-index=26&amp;max-results=25&amp;redirect=false&amp;v=2" /><author><name>Jeremy Likness</name><uri>http://www.blogger.com/profile/18407945801671553594</uri><email>noreply@blogger.com</email></author><generator version="7.00" uri="http://www.blogger.com">Blogger</generator><openSearch:totalResults>124</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/atom+xml" href="http://feeds.feedburner.com/CSharperImage" /><feedburner:info uri="csharperimage" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><link rel="license" type="text/html" href="http://creativecommons.org/licenses/by/3.0/" /><logo>http://jeremylikness.com/signature.gif</logo><entry gd:etag="W/&quot;AkIASHYzeyp7ImA9WxBaEEk.&quot;"><id>tag:blogger.com,1999:blog-8944256652433533647.post-6590041211871342718</id><published>2010-03-18T16:40:00.006-04:00</published><updated>2010-03-19T21:29:09.883-04:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-03-19T21:29:09.883-04:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Managed Extensibility Framework" /><category scheme="http://www.blogger.com/atom/ns#" term="MEF" /><category scheme="http://www.blogger.com/atom/ns#" term="silverlight" /><category scheme="http://www.blogger.com/atom/ns#" term="visual state manager" /><title>Introducing the Visual State Aggregator</title><content type="html">&lt;p&gt;The visual state aggregator. What is it? 
&lt;p&gt;How many times have you found yourself adding freak methods and commands to your Silverlight projects just to manage some animations? It's a common issue, and I've even built solutions like the &lt;a href="http://csharperimage.jeremylikness.com/2010/03/animations-and-view-models.html" target="_blank"&gt;IAnimationDelegate&lt;/a&gt; to help solve the problem. While it works, one thing always bothered me. 
&lt;p&gt;I know it's a &lt;i&gt;View&lt;/i&gt;Model, so it does do things with the view, but should I &lt;i&gt;really&lt;/i&gt; be that concerned with what's going on with the UI? In other words, while it's nice that I can abstract the firing of an animation behind an &lt;code&gt;Action&lt;/code&gt; call and use a command to set it off and then unit test without a real &lt;code&gt;Storyboard&lt;/code&gt; object, it has always felt just a little bit &lt;i&gt;dirty&lt;/i&gt; to do it that way.
&lt;p&gt;&lt;a href="http://www.wintellect.com/CS/files/folders/sample_files/entry12683.aspx" target="_blank"&gt;Download the source code for this post&lt;/a&gt;
&lt;p&gt;I also am a big fan of the &lt;code&gt;VisualStateManager&lt;/code&gt; and got to thinking about whether I ever really need a named story board outside of VSM other than programmatic or complex ones that have to be built at runtime. Looking at the current application I'm working with, which uses some very heavy animated transitions, I realized that all of these could be boiled down to the VSM. 
&lt;p&gt;Consider this scenario: we have two panels. Panel A is active, Panel B is collapsed and off the screen. These are independent controls that probably don't even share the same view model.
&lt;p&gt;&lt;img src="http://gallery.jeremylikness.com/main.php?g2_view=core.DownloadItem&amp;g2_itemId=217&amp;g2_serialNumber=1" title="Initial State"/&gt; 
&lt;p&gt;In this case, I'm going to give Panel A a visual state of "Foreground" and Panel B a visual state of "Offscreen". If you're scratching your head about the visual state manager, take a look at &lt;a href="http://blogs.silverlight.net/blogs/justinangel/archive/2008/12/25/custom-vsm-visualstatemanagers-in-silverlight-2-0.aspx" target="_blank"&gt;Justin Angel's excellent post&lt;/a&gt; on the topic. You can create your own groups and states and have both "final" states and transition states.
&lt;p&gt;&lt;b&gt;Quick Tip: Visibility&lt;/b&gt;
&lt;p&gt;Probably more people abuse visibility by wiring in delegates or commands that set visibility to visible or collapsed (I'm guilty as well) when it's not needed. Stop thinking in terms of visible, collapsed, etc, and start thinking in terms of states. With the visual state manager, this is what your states might look like:
&lt;pre class="brush: xml;"&gt;
&amp;lt;VisualStateGroup x:Name="TransitionStates"&gt;
    &amp;lt;VisualStateGroup.States&gt;
        &amp;lt;VisualState x:Name="Show"&gt;
            &amp;lt;Storyboard&gt;
                &amp;lt;ObjectAnimationUsingKeyFrames BeginTime="00:00:00" Duration="00:00:00.00000" Storyboard.TargetName="LayoutRoot" Storyboard.TargetProperty="(UIElement.Visibility)"&gt;
                    &amp;lt;DiscreteObjectKeyFrame KeyTime="00:00:00"&gt;
                        &amp;lt;DiscreteObjectKeyFrame.Value&gt;
                            &amp;lt;Visibility&gt;Visible&amp;lt;/Visibility&gt;
                        &amp;lt;/DiscreteObjectKeyFrame.Value&gt;
                    &amp;lt;/DiscreteObjectKeyFrame&gt;
                &amp;lt;/ObjectAnimationUsingKeyFrames&gt;
            &amp;lt;/Storyboard&gt;
        &amp;lt;/VisualState&gt;
        &amp;lt;VisualState x:Name="Hide"&gt;
            &amp;lt;Storyboard&gt;
                &amp;lt;ObjectAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="LayoutRoot" Storyboard.TargetProperty="(UIElement.Visibility)"&gt;                                
                    &amp;lt;DiscreteObjectKeyFrame KeyTime="00:00:00"&gt;
                        &amp;lt;DiscreteObjectKeyFrame.Value&gt;
                            &amp;lt;Visibility&gt;Collapsed&amp;lt;/Visibility&gt;
                        &amp;lt;/DiscreteObjectKeyFrame.Value&gt;
                    &amp;lt;/DiscreteObjectKeyFrame&gt;
                &amp;lt;/ObjectAnimationUsingKeyFrames&gt;
             &amp;lt;/Storyboard&gt;
        &amp;lt;/VisualState&gt;
    &amp;lt;/VisualStateGroup.States&gt;
&amp;lt;/VisualStateGroup&gt;
&lt;/pre&gt;
&lt;p&gt;Now you can simply go to a hide or show state, and if you want transitions, you add them to the VSM and voilà! It works ... no need to hard code the transition from collapsed to visible. Now back to our regularly scheduled program ...
&lt;p&gt;When an event happens on Panel A, it goes to the "Background" state and the Panel B goes to the "Onscreen" state. It looks like this: 
&lt;p&gt;&lt;img src="http://gallery.jeremylikness.com/main.php?g2_view=core.DownloadItem&amp;g2_itemId=219&amp;g2_serialNumber=1"/&gt;
&lt;p&gt;Then, when we close Panel B, it goes back to "Offscreen" and the Panel A comes back to foreground. By using visual states, we can manipulate the plane projection and scale transform properties as well as the visibility to achieve our results, and use animations. 
&lt;p&gt;But here's the rub: how can I fire the event in "A" and then let "B" know it's time to change states? 
&lt;p&gt;The most common way I've seen goes something like this: 
&lt;p&gt;Put an &lt;code&gt;Action&lt;/code&gt; or delegate of some sort in a view model. In the code behind or using a behavior (more clever than code behind), attach the desired visual state to the action. Make a command object, and while the command does it's thing, go ahead and call the delegate which in turn flips the visual state. For example, my view model might have:
&lt;pre class="brush: csharp;"&gt;
...
public Action SwapPanelA { get; set; }
...
&lt;/pre&gt;
&lt;p&gt;And in the code-behind, I can wire it up like this: 
&lt;pre class="brush: csharp;"&gt;
...
ViewModel.SwapPanelA = () =&gt; VisualStateManager.GoToState(this, "Foreground", true);
...
&lt;/pre&gt;
&lt;p&gt;And so on and so on. While this certainly decouples it a bit, it also forces us to change the design of our view model to accommodate the transitions. What if we have four controls participating in the same event? Do we wire up a bunch of references for the view model? Does a control bring in a view model only for the sake of wiring in it's animations? 
&lt;p&gt;No, no, no. All wrong (but again, let me elaborate these are things I've tried and worked with in the past, so don't feel bad if you've been doing the same things).
&lt;p&gt;It hit me that I really needed to decouple view actions from business actions. When I click Panel A, the business action might be to call out to a web service to get data to populate in Panel B. I shouldn't care about any transitions.
&lt;p&gt;The view action would be the movement of the panels. 
&lt;p&gt;So how do we decouple this? Enter the Visual State Aggregator. What I decided to do was build an aggregator that could respond to published events by flipping view states. This includes a behavior to participate in an event, and a trigger to push the event out. The first piece is a subscription. A subscription contains a weak reference to a control, an event the control is listening for, and the state the control should go to when the event fires (including whether or not to use transitions). Here is &lt;code&gt;VisualStateSubscription&lt;/code&gt;: 
&lt;pre class="brush: csharp;"&gt;
public class VisualStateSubscription
{
    private readonly WeakReference _targetControl;
    private readonly string _state;
    private readonly bool _useTransitions;
    private readonly string _event;
    private Guid _id = Guid.NewGuid();

    public VisualStateSubscription(Control control, string vsmEvent, string state, bool useTransitions)
    {
        _targetControl = new WeakReference(control);
        _event = vsmEvent;
        _state = state;
        _useTransitions = useTransitions; 
    }

    public bool IsExpired
    {
        get
        {
            return _targetControl == null || !_targetControl.IsAlive || _targetControl.Target == null; 
        }
    }

    public void RaiseEvent(string eventName)
    {
        if (!IsExpired &amp;&amp; _event.Equals(eventName))
        {
            var control = _targetControl.Target as Control;
            VisualStateManager.GoToState(control, _state, _useTransitions); 
        }
    }

    public override bool Equals(object obj)
    {
        return obj is VisualStateSubscription &amp;&amp; ((VisualStateSubscription) obj)._id.Equals(_id);
    }

    public override int GetHashCode()
    {
        return _id.GetHashCode();
    }
}
&lt;/pre&gt;
&lt;p&gt;Next comes the aggregator. It contains the list of subscriptions. It will provide a means to subscribe, as well as a means to publish the event. I decided to use the Managed Extensibility Framework (MEF) to wire it in, so it also gets exported: 
&lt;pre class="brush: csharp;"&gt;
[Export]
public class VisualStateAggregator
{
    private readonly List&amp;lt;VisualStateSubscription&gt; _subscribers = new List&amp;lt;VisualStateSubscription&gt;();

    public void AddSubscription(Control control, string eventName, string stateName, bool useTransitions)
    {
        _subscribers.Add(new VisualStateSubscription(control, eventName, stateName, useTransitions));
    }

    public void PublishEvent(string eventName)
    {
        var expired = new List&amp;lt;VisualStateSubscription&gt;();
        
        foreach(var subscriber in _subscribers)
        {
            if (subscriber.IsExpired)
            {
                expired.Add(subscriber);
            }
            else
            {
                subscriber.RaiseEvent(eventName);
            }
        }

        expired.ForEach(s=&gt;_subscribers.Remove(s));
    }
}
&lt;/pre&gt;
&lt;p&gt;Notice that I take advantage of the event to iterate the subscriptions and remove any that have expired (this means the control went out of scope, and we don't want to force it to hang on with a reference). 
&lt;p&gt;Now there is a behavior to subscribe. First, I want to indicate when a control should participate. This behavior can be attached to any &lt;code&gt;FrameworkElement&lt;/code&gt;. Because the visual state manager only operates on controls, I'll walk the visual tree to find the highest containing control for that element. This way, if you have a grid (which is not a control) inside a user control, it will find the user control and use that as the target. If you don't want to use MEF, just give the aggregator a singleton pattern and reference it here instead of using the import. 
&lt;pre class="brush: csharp;"&gt;
public class VisualStateSubscriptionBehavior : Behavior&amp;lt;FrameworkElement&gt; 
{        
    public VisualStateSubscriptionBehavior()
    {
        CompositionInitializer.SatisfyImports(this);
    }

    [Import]
    public VisualStateAggregator Aggregator { get; set; }

    public string EventName { get; set; }

    public string StateName { get; set; }

    public bool UseTransitions { get; set; }

    protected override void OnAttached()
    {
        AssociatedObject.Loaded += AssociatedObject_Loaded;
    }

    void AssociatedObject_Loaded(object sender, RoutedEventArgs e)
    {
        Control control = null;

        if (AssociatedObject is Control)
        {
            control = AssociatedObject as Control;
        }
        else
        {
            DependencyObject parent = VisualTreeHelper.GetParent(AssociatedObject);
            while (!(parent is Control) &amp;&amp; parent != null)
            {
                parent = VisualTreeHelper.GetParent(parent);
            }
            if (parent is Control)
            {
                control = parent as Control; 
            }
        }

        if (control != null)
        {
            Aggregator.AddSubscription(control, EventName, StateName, UseTransitions);
        }
    }
}
&lt;/pre&gt;
&lt;p&gt;Notice we hook into the loaded event so the visual tree is built prior to walking the tree for our hooks. 
&lt;p&gt;Of course, this implementation gives us a weak or "magic string" event, you could wire that to an enumeration to make that strongly typed. Let's call the event of swapping out Panel A "ActivatePanelB" and the event of bring it back "DeactivatePanelB". Panel A subscribes like this: 
&lt;pre class="brush: xml;"&gt;
&amp;lt;UserControl&gt;
   &amp;lt;Grid x:Name="LayoutRoot"&gt;
   &amp;lt;i:Interaction.Behaviors&gt;
      &amp;lt;vsm:VisualStateSubscriptionBehavior EventName="ActivatePanelB" StateName="Background" UseTransitions="True"/&gt;
      &amp;lt;vsm:VisualStateSubscriptionBehavior EventName="DeactivatePanelB" StateName="Foreground" UseTransitions="True"/&gt;
   &amp;lt;/i:Interaction.Behaviors&gt;
   &amp;lt;/Grid&gt;
&amp;lt;/UserControl&gt;
&lt;/pre&gt;
&lt;p&gt;Then Panel B may subscribe like this: 
&lt;pre class="brush: xml;"&gt;
&amp;lt;UserControl&gt;
   &amp;lt;Grid x:Name="LayoutRoot"&gt;
   &amp;lt;i:Interaction.Behaviors&gt;
      &amp;lt;vsm:VisualStateSubscriptionBehavior EventName="ActivatePanelB" StateName="Onscreen" UseTransitions="True"/&gt;
      &amp;lt;vsm:VisualStateSubscriptionBehavior EventName="DeactivatePanelB" StateName="Offscreen" UseTransitions="True"/&gt;
   &amp;lt;/i:Interaction.Behaviors&gt;
   &amp;lt;/Grid&gt;
&amp;lt;/UserControl&gt;
&lt;/pre&gt;
&lt;p&gt;I'm assuming the visual states are wired up with those names.
&lt;p&gt;Now we need something to trigger an event. We use a trigger action for that. The trigger class is very simple, as it simply needs to publish the event. Because we are using a trigger action, we can bind to any routed event in order for the transition to fire, so this would work for a mouseover that had to animate a separate control for example.
&lt;pre class="brush: csharp;"&gt;
public class VisualStateTrigger : TriggerAction&amp;lt;FrameworkElement&gt; 
{
    public VisualStateTrigger()
    {
        CompositionInitializer.SatisfyImports(this);
    }

    [Import]
    public VisualStateAggregator Aggregator { get; set; }

    public string EventName { get; set; }

    protected override void Invoke(object parameter)
    {
        Aggregator.PublishEvent(EventName);
    }
}
&lt;/pre&gt;
&lt;p&gt;To trigger this, let's say we have a fancy grid with information and clicking on the grid itself fires the event. In Panel A, we'd wire the event like this: 
&lt;pre class="brush: xml;"&gt;
&amp;lt;Grid&gt;
   &amp;lt;i:Interaction.Triggers&gt;
      &amp;lt;i:EventTrigger EventName="MouseLeftButtonUp"&gt;
         &amp;lt;vsm:VisualStateTrigger EventName="ActivatePanelB"/&gt;
      &amp;lt;/i:EventTrigger&gt;
   &amp;lt;/i:Interaction.Triggers&gt;
&amp;lt;/Grid&gt;
&lt;/pre&gt;
&lt;p&gt;In Panel B, we might have a close button: 
&lt;pre class="brush: xml;"&gt;
&amp;lt;Button Content="Close"&gt;
   &amp;lt;i:Interaction.Triggers&gt;
      &amp;lt;i:EventTrigger EventName="Click"&gt;
         &amp;lt;vsm:VisualStateTrigger EventName="DeactivatePanelB"/&gt;
      &amp;lt;/i:EventTrigger&gt;
   &amp;lt;/i:Interaction.Triggers&gt;
&amp;lt;/Button&gt;
&lt;/pre&gt;
&lt;p&gt;And that's it! Without any view models involved, entirely in the UI with the help of our behaviors, we've aggregated the visual state transitions. When you click on the grid, panel A will flip to the "Background" state and animate away, while panel B will flip to the "Onscreen" state and slide in. 
&lt;p&gt;Here is an example for you to have fun with: 
&lt;p&gt;&lt;iframe width="400" height="300" border="0" src="http://apps.jeremylikness.com/samples/visual-state-aggregator/"&gt;&lt;a href="http://apps.jeremylikness.com/samples/visual-state-aggregator/" target="_blank"&gt;Click here to view the sample in a new window&lt;/a&gt;&lt;/iframe&gt;
&lt;p&gt;When you grab the source, you'll find there are absolutely no code-behinds whatsoever other than what is automatically generated. While Panel A and Panel B are completely separate controls that know nothing about each other, the common subscription to a aggregate event coordinates their actions when Panel A is clicked or the close button on Panel B is clicked.
&lt;p&gt;The standalone project for this is included in the download. Enjoy!
&lt;p&gt;P.S. implementing this in my project has been a boon. Was able to eliminate tons of methods and delegates that were there simply to facilitate the VM/View glue. Here's what's nice as well: you can type the events with an enum. If you need to fire an event within your view model, you don't have to find a delegate or grab anything special. Instead, you just import the aggregator and fire your event, like this: 
&lt;pre class="brush: csharp;"&gt;
[Import]
IAggregator Aggregator { get; set; }

private void SomeCode()
{
   Aggregator.RaiseEvent(Events.ActivatePanelB); 
}
&lt;/pre&gt;
&lt;p&gt;That's it! 
&lt;p&gt;&lt;a href="http://www.wintellect.com/CS/files/folders/sample_files/entry12683.aspx" target="_blank"&gt;Download the source code for this post&lt;/a&gt;
&lt;p&gt;&lt;a href="http://jeremylikness.com/" title="Jeremy Likness"&gt;&lt;img border="0" src="http://jeremylikness.com/signature.gif" alt="Jeremy Likness" title="Jeremy Likness"/&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8944256652433533647-6590041211871342718?l=csharperimage.jeremylikness.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/CSharperImage?a=6nOmM-anKtE:b3Wpiau0row:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CSharperImage?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/CSharperImage?a=6nOmM-anKtE:b3Wpiau0row:YwkR-u9nhCs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CSharperImage?d=YwkR-u9nhCs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/CSharperImage?a=6nOmM-anKtE:b3Wpiau0row:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CSharperImage?i=6nOmM-anKtE:b3Wpiau0row:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/CSharperImage?a=6nOmM-anKtE:b3Wpiau0row:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CSharperImage?i=6nOmM-anKtE:b3Wpiau0row:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/CSharperImage?a=6nOmM-anKtE:b3Wpiau0row:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CSharperImage?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/CSharperImage?a=6nOmM-anKtE:b3Wpiau0row:I9og5sOYxJI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CSharperImage?d=I9og5sOYxJI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/CSharperImage/~4/6nOmM-anKtE" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://csharperimage.jeremylikness.com/feeds/6590041211871342718/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://csharperimage.jeremylikness.com/2010/03/introducing-visual-state-aggregator.html#comment-form" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8944256652433533647/posts/default/6590041211871342718?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8944256652433533647/posts/default/6590041211871342718?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/CSharperImage/~3/6nOmM-anKtE/introducing-visual-state-aggregator.html" title="Introducing the Visual State Aggregator" /><author><name>Jeremy Likness</name><uri>http://www.blogger.com/profile/18407945801671553594</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="05667915713066003387" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">2</thr:total><feedburner:origLink>http://csharperimage.jeremylikness.com/2010/03/introducing-visual-state-aggregator.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CkIFRnw8cCp7ImA9WxBbGE4.&quot;"><id>tag:blogger.com,1999:blog-8944256652433533647.post-7862297362669278672</id><published>2010-03-17T08:36:00.002-04:00</published><updated>2010-03-17T08:55:17.278-04:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-03-17T08:55:17.278-04:00</app:edited><title>ViewModel binding with the Managed Extensibility Framework</title><content type="html">&lt;p&gt;This is just a short post to share an "ah-hah" moment I experienced building out a large Managed Extensibility Framework (MEF) Silverlight application. Traditionally, I've wired in the view models using the code behind. I'm not one of those who believes code behind is evil no matter what, so I haven't taken issue with something like this: 
&lt;pre class="brush: csharp;"&gt;
[Import] 
public MainViewModel ViewModel 
{
   get { return LayoutRoot.DataContext as MainViewModel; }
   set { LayoutRoot.DataContext = value; }
}
&lt;/pre&gt;
&lt;p&gt;This simply imports the view model that I need and then passes it along to the data context. The issue with XAML is that it doesn't allow me to pass in constructor information and always creates a "new" instance, so if the view model is part of a larger dependency chain, I'd get a new instance in every page that needed a copy. 
&lt;p&gt;This is an example of when having design patterns as a part of your vocabulary can improve your ability to solve problems. Obviously, it wasn't part of my vocabulary or I wouldn't have missed it! There is a nice pattern that neatly addresses the concern of having a view model wired in by MEF that allows for attaching it in XAML without having to use code behind. Again, I'm not opposed to code behind, but any time I can abstract the behavior further and do it in a natural way without jumping through hoops just to make it work is something I'll consider.
&lt;p&gt;Enter the &lt;a href="http://msdn.microsoft.com/en-us/library/cc707905.aspx" target="_blank"&gt;Service Locator&lt;/a&gt; design pattern. The challenge is that you have components that are based on service contracts and the concrete implementation not known at design time. In our case, the "service" is the view model, and it's not concrete yet because we haven't composed the parts. 
&lt;p&gt;Let's create our service locator for view models. In this example, I only have one, but in the application I am working on there are several, and they all get exposed via the service locator: 
&lt;pre class="brush: csharp;"&gt;
public class ViewModelLocator 
{
   public ViewModelLocator()
   {
      CompositionInitializer.SatisfyImports(this);
   }
  
   [Import]
   public MainViewModel MainViewModelInstance { get; set; }
}
&lt;/pre&gt; 
&lt;p&gt;It's that simple. The class itself composes the view model for us, then provides a property we can use to access the view model. Because we are importing via MEF, we can control the lifetime for the view model and any other attributes we need to compose it properly. Now, we can wire in the view model with no code behind. The XAML looks like this: 
&lt;pre class="brush: xml;"&gt;
&amp;lt;UserControl ... xmlns:vm="clr-namespace:ViewModel"&gt;
&amp;lt;UserControl.Resources&gt;
   &amp;lt;vm:ViewModelLocator x:Key="VMLocator"/&gt;
&amp;lt;/UserControl.Resources&gt;
&amp;lt;Grid
   x:Name="LayoutRoot"
   DataContext={Binding Source={StaticResource VMLocator},Path=MainViewModelInstance}"&gt;
   ...
&amp;lt;/Grid&gt;
&lt;/pre&gt;
&lt;p&gt;There you have it ... a simple, clean way to bind the view model to the view without code behind and still allow MEF to compose all of the parts for you.
&lt;p&gt;&lt;a href="http://jeremylikness.com/" title="Jeremy Likness"&gt;&lt;img border="0" src="http://jeremylikness.com/signature.gif" alt="Jeremy Likness" title="Jeremy Likness"/&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8944256652433533647-7862297362669278672?l=csharperimage.jeremylikness.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/CSharperImage?a=l8yyphrTBuo:52LkrDTa_Rk:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CSharperImage?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/CSharperImage?a=l8yyphrTBuo:52LkrDTa_Rk:YwkR-u9nhCs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CSharperImage?d=YwkR-u9nhCs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/CSharperImage?a=l8yyphrTBuo:52LkrDTa_Rk:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CSharperImage?i=l8yyphrTBuo:52LkrDTa_Rk:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/CSharperImage?a=l8yyphrTBuo:52LkrDTa_Rk:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CSharperImage?i=l8yyphrTBuo:52LkrDTa_Rk:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/CSharperImage?a=l8yyphrTBuo:52LkrDTa_Rk:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CSharperImage?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/CSharperImage?a=l8yyphrTBuo:52LkrDTa_Rk:I9og5sOYxJI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CSharperImage?d=I9og5sOYxJI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/CSharperImage/~4/l8yyphrTBuo" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://csharperimage.jeremylikness.com/feeds/7862297362669278672/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://csharperimage.jeremylikness.com/2010/03/viewmodel-binding-with-managed.html#comment-form" title="4 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8944256652433533647/posts/default/7862297362669278672?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8944256652433533647/posts/default/7862297362669278672?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/CSharperImage/~3/l8yyphrTBuo/viewmodel-binding-with-managed.html" title="ViewModel binding with the Managed Extensibility Framework" /><author><name>Jeremy Likness</name><uri>http://www.blogger.com/profile/18407945801671553594</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="05667915713066003387" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">4</thr:total><feedburner:origLink>http://csharperimage.jeremylikness.com/2010/03/viewmodel-binding-with-managed.html</feedburner:origLink></entry><entry gd:etag="W/&quot;D0AHSXoyfCp7ImA9WxBbFEg.&quot;"><id>tag:blogger.com,1999:blog-8944256652433533647.post-1353402351049325282</id><published>2010-03-12T23:24:00.004-05:00</published><updated>2010-03-12T23:48:58.494-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-03-12T23:48:58.494-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Managed Extensibility Framework" /><category scheme="http://www.blogger.com/atom/ns#" term="MEF" /><category scheme="http://www.blogger.com/atom/ns#" term="metadata" /><category scheme="http://www.blogger.com/atom/ns#" term="regions" /><title>Custom Export Providers with Custom Metadata for Region Management</title><content type="html">&lt;p&gt;Over the past few weeks I've been exploring the concept of region management using the Managed Extensibility Framework, and for a good reason. I'm working on a project that has several different regions and controls that must be managed effectively and across the boundaries of dynamic XAP files in Silverlight 3. 
&lt;p&gt;Sound like a mouthful? In previous posts I demonstrated some methods for handling region management using MEF. This post is an advanced post and I'm assuming you have the fundamentals of MEF down. If not, I would come back to this post at a later time. You'll also want to be familiar with my previous experiments detailed in &lt;a href="http://csharperimage.jeremylikness.com/2010/03/mef-instead-of-prism-for-silverlight-3.html" target="_blank"&gt;this article&lt;/a&gt; and another version in &lt;a href="http://csharperimage.jeremylikness.com/2010/03/mvvm-with-mef-in-silverlight-video_09.html" target="_blank"&gt;this video tutorial&lt;/a&gt;.
&lt;p&gt;So the ultimate goal for me is to tag a view with a type, tag a region with a type, then route views to regions and vice versa. This way I can easily add controls (just tag 'em) and regions (again, tag 'em) and have a routing table that handles swapping them in and out for me. 
&lt;p&gt;One of the issues in the past has been having to explicitly export the region. In other words, I might have a &lt;code&gt;ContentControl&lt;/code&gt; tagged for a particular region. I have to give it an &lt;code&gt;x:Name&lt;/code&gt; in the XAML, like this:
&lt;pre class="brush: xml;"&gt;
...
&amp;lt;ContentControl x:Name="MyName"/&gt;
...
&lt;/pre&gt;
&lt;p&gt;And then export it with my custom attributes like this: 
&lt;pre class="brush: csharp;"&gt;
...
[TargetRegion(Region=ViewRegion.MainRegion)]
public FrameworkElement MainRegionExport 
{
   get { return MyName; }
}
...
&lt;/pre&gt;
&lt;p&gt;This assumes I created a custom export attribute with a &lt;code&gt;Region&lt;/code&gt; parameter and a base type of FrameworkElement. Where I want to go is here: eliminate the code behind, and tag my regions like this: 
&lt;pre class="brush: xml;"&gt;
...
&amp;lt;ContentControl mef:TargetRegion.Region="MainRegion"/&gt;
...
&lt;/pre&gt;
&lt;p&gt;In the XAML, with no code behind. Can we get there? Of course, this is MEF! 
&lt;p&gt;The first step for me is to create to a custom export provider. I spoke briefly about this in an old post: &lt;a href="http://csharperimage.jeremylikness.com/2009/12/silverlight-mef-custom-exportprovider.html" target="_blank"&gt;Custom Export Provider for Attached Exports&lt;/a&gt;, but that was for static controls. Here, I want to export regions with meta data. The export provider looks like this: 
&lt;pre class="brush: csharp;"&gt;
public class RegionExportProvider : ExportProvider
{
    private static readonly Dictionary&amp;lt;ExportDefinition, List&amp;lt;Export&gt;&gt; _exports = new Dictionary&amp;lt;ExportDefinition, List&amp;lt;Export&gt;&gt;();

    private static readonly RegionExportProvider _provider = new RegionExportProvider();

    public static DependencyProperty RegionProperty = 
        DependencyProperty.RegisterAttached(
        "Region", 
        typeof(ViewRegion), 
        typeof(RegionExportProvider),
        null);       

    public static ViewRegion GetRegion(DependencyObject obj)
    {
        return (ViewRegion) obj.GetValue(RegionProperty);
    }

    public static void SetRegion(DependencyObject obj, ViewRegion value)
    {
        obj.SetValue(RegionProperty, value);
        GetRegionExportProvider().AddExport(value, obj);
    }

    private static readonly object _sync = new object();

    public static RegionExportProvider GetRegionExportProvider()
    {
        return _provider;
    }

    public void AddExport(ViewRegion region, object export)
    {
        lock (_sync)
        {
            string contractName = typeof (FrameworkElement).FullName;

            var metadata = new Dictionary&amp;lt;string, object&gt;
                               {
                                   {"ExportTypeIdentity", typeof (FrameworkElement).FullName},
                               }; 

            var found =
                from e in _exports
                where string.Compare(e.Key.ContractName, contractName, StringComparison.OrdinalIgnoreCase) == 0
                select e;
            
            if (found.Count() == 0)
            {                    
                var definition =
                    new ExportDefinition(contractName, metadata);

                Debug.WriteLine("Region Export Provider: Add custom export: " + region);

                _exports.Add(definition, new List&amp;lt;Export&gt;());
            }

            metadata.Add("Region", region); 

            var wrapper =
                new Export(contractName, 
                    metadata, 
                    () =&gt; export);

            found.First().Value.Add(wrapper);
        }
    }

    protected override IEnumerable&amp;lt;Export&gt; GetExportsCore(ImportDefinition definition, AtomicComposition atomicComposition)
    {
        var contractDefinition = definition as ContractBasedImportDefinition;
        IEnumerable&amp;lt;Export&gt; retVal = Enumerable.Empty&amp;lt;Export&gt;();
        
        if (contractDefinition != null)
        {
            string contractName =
                contractDefinition.ContractName;
            
            Debug.WriteLine("GetExportsCore: Request for contract: " + contractName);

            if (!string.IsNullOrEmpty(contractName))
            {
                var exports =
                    from e in _exports
                    where string.Compare(e.Key.ContractName, contractName, StringComparison.OrdinalIgnoreCase) == 0
                    &amp;&amp; definition.IsConstraintSatisfiedBy(e.Key)
                    select e.Value;

                if (exports.Count() &gt; 0)
                {
                    Debug.WriteLine("Export satisfied.");
                    retVal = exports.First();
                }
                else
                {
                    Debug.WriteLine("Export was not satisfied.");
                }
            }
        }

        return retVal;
    }
}
&lt;/pre&gt;
&lt;p&gt;Let's step through it. First, I need to keep a catalog of my exports. These are unique type definitions and contract names that we are going to satisfied with our custom export provider. I use the singleton pattern because I'm going to double this class as an attached behavior. Probably violating the single responsibility principle here, and could break it out, but let's run with it for now. Sometimes it makes sense to keep the code together for readability and maintainability. 
&lt;p&gt;The attached property just takes the type of the region. Because we type it to the enumeration, intellisense will work in the XAML when adding the behavior, which is nice, because it makes it less of a "magic string" for us to use.
&lt;p&gt;The key to note is the setter. When we set the value, we add the export. The export itself is going to be the contract name and the type identity. This is why we add the first bit of meta data, the &lt;code&gt;ExportTypeIdentity&lt;/code&gt;, and then see if we've already made an entry or not. If not, we add a new entry with an empty list of the actual exports. 
&lt;p&gt;Adding the exports is easy. Metadata on an export is really just a dictionary of labels and values. We know this particular export has one label ("Region") and that it is the enum of the region type. Therefore, once we find or create our export definition, we go ahead and add the export with the region itself (a content control, items control, or other container) and meta data for that region (in this case, the "Region" tag and the enumeration value). 
&lt;p&gt;Now we just need to be prepared to supply the exports when our custom provider is queried. This is the &lt;code&gt;GetExportsCore&lt;/code&gt;. Fortunately, we get it easy. Instead of having to keep track of all of the rules, the import definition comes with a &lt;code&gt;IsConstraintSatisfiedBy&lt;/code&gt; method that calls the &lt;code&gt;Constraint&lt;/code&gt; provided to filter the export values. We simply find the definition that matches the contract and the constraint, then provide all of the exports we have. These will then have their meta data parsed and if a capabilities interface is provided, it will be populated with the values so that the &lt;code&gt;Lazy&amp;lt;Type,ITypeCapabilities&gt;&lt;/code&gt; target can be populated. Notice I added some debug lines to help troubleshoot. 
&lt;p&gt;Now I can tag my export the way I wanted to: 
&lt;pre class="brush: xml;"&gt;
...
&amp;lt;ContentControl mef:RegionExportProvider.Region="MainRegion" .../&gt;
...
&lt;/pre&gt;
&lt;p&gt;There is only one more step I need to take in order for this all to work. Remember back when I showed you how to override the container so we could continue to compose new &lt;code&gt;DeploymentCatalogs&lt;/code&gt; into an &lt;code&gt;AggregateCatalog&lt;/code&gt; as they became available? When we create that special container, we need to add our secret sauce. We do it like this: 
&lt;pre class="brush: csharp;"&gt;
...
var container = new CompositionContainer(catalogService.GetCatalog(), RegionExportProvider.GetRegionExportProvider());
...
&lt;/pre&gt; 
&lt;p&gt;Now we've told the container to query our own custom export provider when trying to satisfy parts. 
&lt;p&gt;If you recall from my prior posts, I used a routing class to map view types to regions, and loaded the regions like this: 
&lt;pre class="brush: csharp;"&gt;
[ImportMany(AllowRecomposition = true)]
public Lazy&amp;lt;FrameworkElement, ITargetRegionCapabilities&gt;[] RegionImports { get; set; }
&lt;/pre&gt;
&lt;p&gt;Our new provider kindly exports the tagged regions, which are then imported with the routing class and used to swap views in and out of the display.
&lt;p&gt;&lt;a href="http://jeremylikness.com/" title="Jeremy Likness"&gt;&lt;img border="0" src="http://jeremylikness.com/signature.gif" alt="Jeremy Likness" title="Jeremy Likness"/&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8944256652433533647-1353402351049325282?l=csharperimage.jeremylikness.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/CSharperImage?a=ApfUEh3-y8U:Ax-bhsDsykE:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CSharperImage?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/CSharperImage?a=ApfUEh3-y8U:Ax-bhsDsykE:YwkR-u9nhCs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CSharperImage?d=YwkR-u9nhCs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/CSharperImage?a=ApfUEh3-y8U:Ax-bhsDsykE:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CSharperImage?i=ApfUEh3-y8U:Ax-bhsDsykE:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/CSharperImage?a=ApfUEh3-y8U:Ax-bhsDsykE:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CSharperImage?i=ApfUEh3-y8U:Ax-bhsDsykE:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/CSharperImage?a=ApfUEh3-y8U:Ax-bhsDsykE:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CSharperImage?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/CSharperImage?a=ApfUEh3-y8U:Ax-bhsDsykE:I9og5sOYxJI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CSharperImage?d=I9og5sOYxJI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/CSharperImage/~4/ApfUEh3-y8U" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://csharperimage.jeremylikness.com/feeds/1353402351049325282/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://csharperimage.jeremylikness.com/2010/03/custom-export-providers-with-custom.html#comment-form" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8944256652433533647/posts/default/1353402351049325282?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8944256652433533647/posts/default/1353402351049325282?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/CSharperImage/~3/ApfUEh3-y8U/custom-export-providers-with-custom.html" title="Custom Export Providers with Custom Metadata for Region Management" /><author><name>Jeremy Likness</name><uri>http://www.blogger.com/profile/18407945801671553594</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="05667915713066003387" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">2</thr:total><feedburner:origLink>http://csharperimage.jeremylikness.com/2010/03/custom-export-providers-with-custom.html</feedburner:origLink></entry><entry gd:etag="W/&quot;D0EAQH48fCp7ImA9WxBbFE0.&quot;"><id>tag:blogger.com,1999:blog-8944256652433533647.post-8458122449922645946</id><published>2010-03-12T09:50:00.003-05:00</published><updated>2010-03-12T09:54:01.074-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-03-12T09:54:01.074-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Managed Extensibility Framework" /><category scheme="http://www.blogger.com/atom/ns#" term="MEF" /><category scheme="http://www.blogger.com/atom/ns#" term="silverlight" /><title>Advanced Silverlight Applications using the Managed Extensibility Framework</title><content type="html">&lt;p&gt;Voting for this year's &lt;a href="http://www.codestock.org/" target="_blank"&gt;CodeStock&lt;/a&gt; sessions has begun. The conference will be held in Knoxville, Tennessee on June 25th and June 26th. The conference is only $55.00 USD to attend if you register before May 3rd. Most sessions are determined based on vote by attendees. 
&lt;p&gt;If you are interested in attending, you may &lt;a href="http://codestock.org/Pages/Register.aspx" target="_blank"&gt;register to attend&lt;/a&gt; here. The details of my session and place you can vote for it is here: &lt;a href="http://codestock.org/sessions/advanced-silverlight-applications-using-the-managed-extensibility-framework-mef.aspx" target="_blank"&gt;Building Advanced Silverlight Applications using the Managed Extensibility Framework&lt;/a&gt;. Thanks, and I hope to see you there!  
&lt;p&gt;&lt;a href="http://jeremylikness.com/" title="Jeremy Likness"&gt;&lt;img border="0" src="http://jeremylikness.com/signature.gif" alt="Jeremy Likness" title="Jeremy Likness"/&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8944256652433533647-8458122449922645946?l=csharperimage.jeremylikness.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/CSharperImage?a=r_gfSgOlro0:LKj_vjHnIq8:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CSharperImage?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/CSharperImage?a=r_gfSgOlro0:LKj_vjHnIq8:YwkR-u9nhCs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CSharperImage?d=YwkR-u9nhCs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/CSharperImage?a=r_gfSgOlro0:LKj_vjHnIq8:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CSharperImage?i=r_gfSgOlro0:LKj_vjHnIq8:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/CSharperImage?a=r_gfSgOlro0:LKj_vjHnIq8:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CSharperImage?i=r_gfSgOlro0:LKj_vjHnIq8:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/CSharperImage?a=r_gfSgOlro0:LKj_vjHnIq8:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CSharperImage?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/CSharperImage?a=r_gfSgOlro0:LKj_vjHnIq8:I9og5sOYxJI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CSharperImage?d=I9og5sOYxJI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/CSharperImage/~4/r_gfSgOlro0" height="1" width="1"/&gt;</content><link rel="related" href="http://codestock.org/sessions/advanced-silverlight-applications-using-the-managed-extensibility-framework-mef.aspx" title="Advanced Silverlight Applications using the Managed Extensibility Framework" /><link rel="replies" type="application/atom+xml" href="http://csharperimage.jeremylikness.com/feeds/8458122449922645946/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://csharperimage.jeremylikness.com/2010/03/advanced-silverlight-applications-using.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8944256652433533647/posts/default/8458122449922645946?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8944256652433533647/posts/default/8458122449922645946?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/CSharperImage/~3/r_gfSgOlro0/advanced-silverlight-applications-using.html" title="Advanced Silverlight Applications using the Managed Extensibility Framework" /><author><name>Jeremy Likness</name><uri>http://www.blogger.com/profile/18407945801671553594</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="05667915713066003387" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://csharperimage.jeremylikness.com/2010/03/advanced-silverlight-applications-using.html</feedburner:origLink></entry><entry gd:etag="W/&quot;C0UNR3o5fyp7ImA9WxBbEUQ.&quot;"><id>tag:blogger.com,1999:blog-8944256652433533647.post-8770175966746310005</id><published>2010-03-09T22:14:00.003-05:00</published><updated>2010-03-09T22:21:36.427-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-03-09T22:21:36.427-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="mvvm" /><category scheme="http://www.blogger.com/atom/ns#" term="MEF" /><category scheme="http://www.blogger.com/atom/ns#" term="plugin" /><title>MVVM with MEF in Silverlight Video Tutorial Part 2: Plugins and Metadata</title><content type="html">&lt;p&gt;In the &lt;a href="http://csharperimage.jeremylikness.com/2010/03/mvvm-with-mef-in-silverlight-video.html" target="_blank"&gt;first part&lt;/a&gt; of this series, I demonstrated a very simple project that used MVVM (Model-View-ViewModel) along with the Managed Extensibility Framework to produce a simple screen that toggled between a square and a circle. 
&lt;p&gt;In this next video, I am re-designing the original project. This video starts with the original solution, but then I rework the code, using metadata, to turn the shapes into plugins. I duplicate the original effort with the new design (using a combobox instead of a checkbox because now we can support 1 ... n plugins) and then show how easy it is to add a new plugin with the architecture. 
&lt;p&gt;&lt;a href="http://www.wintellect.com/CS/files/folders/sample_files/entry12477.aspx" target="_blank"&gt;Download the source code for this project.&lt;/a&gt;
&lt;p&gt;
&lt;p&gt;&lt;iframe width="640" height="480" border="0" margin="2" src="http://jeremylikness.com/video/mvvm-and-mef-with-silverlight-part-2/"&gt;&lt;a href="http://jeremylikness.com/video/mvvm-and-mef-with-silverlight-part-2/" target="_blank"&gt;Click here to play in a new window&lt;/a&gt;&lt;/iframe&gt;
&lt;p&gt;
&lt;p&gt;Here is the final application:
&lt;p&gt;
&lt;p&gt;&lt;iframe width="400" height="300" border="0" margin="2" src="http://apps.jeremylikness.com/samples/mvvm-with-mef-plugin-example/MEFMVVMDemoTestPage.html"&gt;&lt;a href="http://apps.jeremylikness.com/samples/mvvm-with-mef-plugin-example/MEFMVVMDemoTestPage.html" target="_blank"&gt;Click here to view the Silverlight application in a new window&lt;/a&gt;&lt;/iframe&gt;
&lt;p&gt;
&lt;p&gt;&lt;a href="http://www.wintellect.com/CS/files/folders/sample_files/entry12477.aspx" target="_blank"&gt;Download the source code for this project.&lt;/a&gt;
&lt;p&gt;&lt;a href="http://jeremylikness.com/" title="Jeremy Likness"&gt;&lt;img border="0" src="http://jeremylikness.com/signature.gif" alt="Jeremy Likness" title="Jeremy Likness"/&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8944256652433533647-8770175966746310005?l=csharperimage.jeremylikness.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/CSharperImage?a=tkQLIC3TS_4:J9SKp4D37q0:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CSharperImage?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/CSharperImage?a=tkQLIC3TS_4:J9SKp4D37q0:YwkR-u9nhCs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CSharperImage?d=YwkR-u9nhCs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/CSharperImage?a=tkQLIC3TS_4:J9SKp4D37q0:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CSharperImage?i=tkQLIC3TS_4:J9SKp4D37q0:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/CSharperImage?a=tkQLIC3TS_4:J9SKp4D37q0:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CSharperImage?i=tkQLIC3TS_4:J9SKp4D37q0:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/CSharperImage?a=tkQLIC3TS_4:J9SKp4D37q0:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CSharperImage?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/CSharperImage?a=tkQLIC3TS_4:J9SKp4D37q0:I9og5sOYxJI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CSharperImage?d=I9og5sOYxJI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/CSharperImage/~4/tkQLIC3TS_4" height="1" width="1"/&gt;</content><link rel="related" href="http://jeremylikness.com/video/mvvm-and-mef-with-silverlight-part-2/" title="MVVM with MEF in Silverlight Video Tutorial Part 2: Plugins and Metadata" /><link rel="enclosure" type="video/mp4" href="http://jeremylikness.com/video/mvvm-and-mef-with-silverlight-part-2/mvvmmef2.mp4" length="0" /><link rel="replies" type="application/atom+xml" href="http://csharperimage.jeremylikness.com/feeds/8770175966746310005/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://csharperimage.jeremylikness.com/2010/03/mvvm-with-mef-in-silverlight-video_09.html#comment-form" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8944256652433533647/posts/default/8770175966746310005?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8944256652433533647/posts/default/8770175966746310005?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/CSharperImage/~3/tkQLIC3TS_4/mvvm-with-mef-in-silverlight-video_09.html" title="MVVM with MEF in Silverlight Video Tutorial Part 2: Plugins and Metadata" /><author><name>Jeremy Likness</name><uri>http://www.blogger.com/profile/18407945801671553594</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="05667915713066003387" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">2</thr:total><feedburner:origLink>http://csharperimage.jeremylikness.com/2010/03/mvvm-with-mef-in-silverlight-video_09.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CEYGRHsyfip7ImA9WxBUGUQ.&quot;"><id>tag:blogger.com,1999:blog-8944256652433533647.post-3130147511676494531</id><published>2010-03-07T00:02:00.006-05:00</published><updated>2010-03-07T15:02:05.596-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-03-07T15:02:05.596-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Managed Extensibility Framework" /><category scheme="http://www.blogger.com/atom/ns#" term="mvvm" /><category scheme="http://www.blogger.com/atom/ns#" term="MEF" /><category scheme="http://www.blogger.com/atom/ns#" term="silverlight" /><category scheme="http://www.blogger.com/atom/ns#" term="model-view-viewmodel" /><title>MVVM with MEF in Silverlight: Video Tutorial</title><content type="html">&lt;p&gt;This is a video tutorial to introduce beginners to how to use both MVVM (Model-View-ViewModel) and MEF (Managed Extensibility Framework) with Silverlight (should work for versions 3 and 4). Of course, some "veterans" may want to watch as well in case you've missed some of the fundamentals, or have a clever way to do something that you can share in the comments for future visitors to the page. 
&lt;p&gt;In this edition, I build a simple application that allows the user to check a preference on the screen (whether they prefer squares over circles) and then displays a square or a circle. We use MVVM and wire everything together with MEF.
&lt;p&gt;Download the source code: &lt;a href="http://www.wintellect.com/CS/files/folders/sample_files/entry12353.aspx" target="_blank"&gt;MEFMVVMDemoSln.zip&lt;/a&gt;
&lt;p&gt;Click here to watch the video directly if it doesn't appear in the frame below (recommended to watch in full screen): &lt;a href="http://jeremylikness.com/video/mvvm-and-mef-with-silverlight-part-1/" target="_blank"&gt;Watch the video in a separate window&lt;/a&gt;
&lt;p&gt;
&lt;p&gt;&lt;iframe width="640" height="480" src="http://jeremylikness.com/video/mvvm-and-mef-with-silverlight-part-1/" margin="2"&gt;&lt;a href="http://jeremylikness.com/video/mvvm-and-mef-with-silverlight-part-1/" target="_blank"&gt;Video Tutorial: Model-View-ViewModel with the Managed Extensibility Framework in Silverlight&lt;/a&gt;&lt;/iframe&gt;
&lt;p&gt;
&lt;p&gt;Here is the final application:
&lt;p&gt;
&lt;iframe width="400" height="300" src="http://apps.jeremylikness.com/samples/model-view-viewmodel-and-managed-extensibility-framework/MEFMVVMDemoTestPage.html" margin="2"&gt;&lt;a href="http://apps.jeremylikness.com/samples/model-view-viewmodel-and-managed-extensibility-framework/MEFMVVMDemoTestPage.html" target="_blank"&gt;Model-View-ViewModel example with the Managed Extensibility Framework in Silverlight&lt;/a&gt;&lt;/iframe&gt;
&lt;p&gt;Download the source code: &lt;a href="http://www.wintellect.com/CS/files/folders/sample_files/entry12353.aspx" target="_blank"&gt;MEFMVVMDemoSln.zip&lt;/a&gt;
&lt;p&gt;&lt;a href="http://jeremylikness.com/" title="Jeremy Likness"&gt;&lt;img border="0" src="http://jeremylikness.com/signature.gif" alt="Jeremy Likness" title="Jeremy Likness"/&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8944256652433533647-3130147511676494531?l=csharperimage.jeremylikness.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/CSharperImage?a=fozkPTt5DAI:lZwVC6M2I3E:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CSharperImage?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/CSharperImage?a=fozkPTt5DAI:lZwVC6M2I3E:YwkR-u9nhCs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CSharperImage?d=YwkR-u9nhCs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/CSharperImage?a=fozkPTt5DAI:lZwVC6M2I3E:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CSharperImage?i=fozkPTt5DAI:lZwVC6M2I3E:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/CSharperImage?a=fozkPTt5DAI:lZwVC6M2I3E:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CSharperImage?i=fozkPTt5DAI:lZwVC6M2I3E:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/CSharperImage?a=fozkPTt5DAI:lZwVC6M2I3E:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CSharperImage?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/CSharperImage?a=fozkPTt5DAI:lZwVC6M2I3E:I9og5sOYxJI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CSharperImage?d=I9og5sOYxJI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/CSharperImage/~4/fozkPTt5DAI" height="1" width="1"/&gt;</content><link rel="related" href="http://jeremylikness.com/video/mvvm-and-mef-with-silverlight-part-1/" title="MVVM with MEF in Silverlight: Video Tutorial" /><link rel="replies" type="application/atom+xml" href="http://csharperimage.jeremylikness.com/feeds/3130147511676494531/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://csharperimage.jeremylikness.com/2010/03/mvvm-with-mef-in-silverlight-video.html#comment-form" title="6 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8944256652433533647/posts/default/3130147511676494531?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8944256652433533647/posts/default/3130147511676494531?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/CSharperImage/~3/fozkPTt5DAI/mvvm-with-mef-in-silverlight-video.html" title="MVVM with MEF in Silverlight: Video Tutorial" /><author><name>Jeremy Likness</name><uri>http://www.blogger.com/profile/18407945801671553594</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="05667915713066003387" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">6</thr:total><feedburner:origLink>http://csharperimage.jeremylikness.com/2010/03/mvvm-with-mef-in-silverlight-video.html</feedburner:origLink></entry><entry gd:etag="W/&quot;D0ICQX4-fCp7ImA9WxBUF04.&quot;"><id>tag:blogger.com,1999:blog-8944256652433533647.post-4660380987514157216</id><published>2010-03-04T15:21:00.007-05:00</published><updated>2010-03-04T15:46:00.054-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-03-04T15:46:00.054-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="silverlight" /><category scheme="http://www.blogger.com/atom/ns#" term="line of business" /><title>Silverlight Line of Business Applications</title><content type="html">&lt;p&gt;A few weeks ago, I had the privilege of presenting a talk entitled, "Silverlight Line of Business Applications" at the &lt;a href="http://www.meetup.com/The-Atlanta-Silverlight-Meetup-Group/" target="_blank"&gt;Atlanta Silverlight Meetup Group&lt;/a&gt;. This talk focused on several aspects of building line of business applications, ranging from the principles that belong in the foundation or architecture, to specific frameworks and methodologies. 
&lt;p&gt;You can view the video below, or link directly &lt;a href="http://jeremylikness.com/video/silverlight-line-of-business-applications/" target="_blank"&gt;by clicking here.&lt;/a&gt; I did take some time to encode chapters, so if you click the chapter icon in the player, you can jump to sections. I was hesitant to post this because there was not a microphone at the event. I spoke loud and recorded the talk via the built-in laptop microphone but the sound quality suffered as a result and there is plenty of background noise. 
&lt;p&gt;I hope the value of the content makes up for the poor audio quality. Here is the table of contents:
&lt;ul&gt;&lt;li&gt;What is "Line of Business"?&lt;li&gt;Frameworks and Tools&lt;li&gt;Demo: Unit Testing Framework&lt;li&gt;Data Access Strategies&lt;li&gt;WCF RIA Services&lt;li&gt;Demo: RIA with POCO&lt;li&gt;UI Modularity and Scalability&lt;li&gt;Silverlight 4 and Beyond&lt;/ul&gt;
&lt;p&gt;I hope you enjoy the video and appreciate any comments or feedback you may have!
&lt;br/&gt;&lt;br/&gt;
&lt;iframe frameborder="0" src="http://jeremylikness.com/video/silverlight-line-of-business-applications/" width="644" height="484" marginwidth="2" marginheight="2"&gt;&lt;a href="http://jeremylikness.com/video/silverlight-line-of-business-applications/"&gt;Click here if you don't see the video&lt;/a&gt;&lt;/iframe&gt;
&lt;p&gt;&lt;a href="http://jeremylikness.com/" title="Jeremy Likness"&gt;&lt;img border="0" src="http://jeremylikness.com/signature.gif" alt="Jeremy Likness" title="Jeremy Likness"/&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8944256652433533647-4660380987514157216?l=csharperimage.jeremylikness.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/CSharperImage?a=Niy7a8gK1xE:8cNkW0Jdipw:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CSharperImage?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/CSharperImage?a=Niy7a8gK1xE:8cNkW0Jdipw:YwkR-u9nhCs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CSharperImage?d=YwkR-u9nhCs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/CSharperImage?a=Niy7a8gK1xE:8cNkW0Jdipw:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CSharperImage?i=Niy7a8gK1xE:8cNkW0Jdipw:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/CSharperImage?a=Niy7a8gK1xE:8cNkW0Jdipw:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CSharperImage?i=Niy7a8gK1xE:8cNkW0Jdipw:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/CSharperImage?a=Niy7a8gK1xE:8cNkW0Jdipw:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CSharperImage?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/CSharperImage?a=Niy7a8gK1xE:8cNkW0Jdipw:I9og5sOYxJI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CSharperImage?d=I9og5sOYxJI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/CSharperImage/~4/Niy7a8gK1xE" height="1" width="1"/&gt;</content><link rel="related" href="http://jeremylikness.com/video/silverlight-line-of-business-applications/" title="Silverlight Line of Business Applications" /><link rel="enclosure" type="video/mp4" href="http://jeremylikness.com/video/silverlight-line-of-business-applications/SilverlightLOB.mp4" length="0" /><link rel="enclosure" type="image/jpeg" href="http://jeremylikness.com/video/silverlight-line-of-business-applications/SilverlightLOB_Thumb.jpg" length="0" /><link rel="replies" type="application/atom+xml" href="http://csharperimage.jeremylikness.com/feeds/4660380987514157216/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://csharperimage.jeremylikness.com/2010/03/silverlight-line-of-business.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8944256652433533647/posts/default/4660380987514157216?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8944256652433533647/posts/default/4660380987514157216?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/CSharperImage/~3/Niy7a8gK1xE/silverlight-line-of-business.html" title="Silverlight Line of Business Applications" /><author><name>Jeremy Likness</name><uri>http://www.blogger.com/profile/18407945801671553594</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="05667915713066003387" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://csharperimage.jeremylikness.com/2010/03/silverlight-line-of-business.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CkMESXc9cSp7ImA9WxBUFk4.&quot;"><id>tag:blogger.com,1999:blog-8944256652433533647.post-3101066328428581981</id><published>2010-03-03T10:16:00.002-05:00</published><updated>2010-03-03T10:33:28.969-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-03-03T10:33:28.969-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="silverlight" /><category scheme="http://www.blogger.com/atom/ns#" term="animation" /><category scheme="http://www.blogger.com/atom/ns#" term="storyboard" /><title>Animations and View Models: IAnimationDelegate</title><content type="html">&lt;p&gt;We often trip over ourselves trying to minimize code behind and abstract behaviors in the UI from the models, etc. This is important for clean separation, but sometimes behaviors may add too much abstraction. The real fact is many applications require some sort of transition or animation based on events, and while we can try to put as many of those as possible into the &lt;code&gt;VisualStateManager&lt;/code&gt;, there may be instances such as dynamically created animations or special triggers that end up involving the view model somehow.
&lt;p&gt;What I'm proposing here is a very simple solution to allowing your view model to fire and respond to animations without having to know about those animations. The view model knows it has to fire some event, and may want notification when the event is done, but how that event is implemented is up to you. This way, the live version can contain &lt;code&gt;Storyboard&lt;/code&gt; objects while the unit tests can contain mocks. 
&lt;p&gt;First, let's create a simple interface that our view model can talk to. It simply begins the animation and provides a callback when the animation is complete. (If you like, you can make it even more generic and call it a transition or an event).
&lt;pre class="brush: csharp;"&gt;
public interface IAnimationDelegate
{
    void BeginAnimation(Action animationComplete);
}
&lt;/pre&gt;
&lt;p&gt;That's pretty simple. Now, in my view model, I can fire the event and react. In this totally contrived example, whenever our first value changes, we fire a transition and only when the transition is complete, we move it with some changes to a second value. 
&lt;pre class="brush: csharp;"&gt;
public class MyViewModel : BaseNotify 
{
   public IAnimationDelegate Value1Transition { get; set; }

   private string _value1; 

   public string Value1 
   { 
      get { return _value1; } 
      set {
              _value1 = value;
              Value1Transition.BeginAnimation(_Value1Transitioned);
              RaisePropertyChanged("Value1"); 
          }
    }

    private string _value2; 

    public string Value2 
    {
       get { return _value2; }
       set {
             _value2 = value; 
             RaisePropertyChanged("Value2");
           }       
    }

    private void _Value1Transitioned()
    {
       Value2 = "This was the first value: " + Value1; 
    }
}    
&lt;/pre&gt;
&lt;p&gt;The implementation of the animation delegate class might look like this: 
&lt;pre class="brush: csharp;"&gt;
public class AnimationDelegate : IAnimationDelegate
{
    private readonly Storyboard _storyboard;

    private Action _animationComplete;

    public AnimationDelegate(Storyboard storyboard)
    {
        _storyboard = storyboard;
        _storyboard.Completed += StoryboardCompleted;
    }

    void StoryboardCompleted(object sender, EventArgs e)
    {
        if (_animationComplete != null)
        {
            _animationComplete();
        }
    }

    public void BeginAnimation(Action animationComplete)
    {
        _animationComplete = animationComplete;
        _storyboard.Begin();
    }
}
&lt;/pre&gt;
&lt;p&gt;We could unregister the event when completed, add other parameters to stop it when completed, etc, but this is a good staring point. 
&lt;p&gt;Now I simply need to wire the delegate. If my animation is called &lt;code&gt;AnimateValue1&lt;/code&gt; then with the Managed Extensibility Framework (MEF), I'd do something like this in the code behind for my control: 
&lt;pre class="brush: csharp;"&gt;
[Import]
public MyViewModel ViewModel
{
   get {  return LayoutRoot.DataContext as MyViewModel; }
   set {
          value.Value1Transition = new AnimationDelegate(AnimateValue1); 
          LayoutRoot.DataContext = value;          
       }
}
&lt;/pre&gt;
&lt;p&gt;... and there you have it.
&lt;p&gt;&lt;a href="http://jeremylikness.com/" title="Jeremy Likness"&gt;&lt;img border="0" src="http://jeremylikness.com/signature.gif" alt="Jeremy Likness" title="Jeremy Likness"/&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8944256652433533647-3101066328428581981?l=csharperimage.jeremylikness.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/CSharperImage?a=KxUYu3-RIfc:qdTHQ0bfyUQ:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CSharperImage?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/CSharperImage?a=KxUYu3-RIfc:qdTHQ0bfyUQ:YwkR-u9nhCs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CSharperImage?d=YwkR-u9nhCs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/CSharperImage?a=KxUYu3-RIfc:qdTHQ0bfyUQ:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CSharperImage?i=KxUYu3-RIfc:qdTHQ0bfyUQ:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/CSharperImage?a=KxUYu3-RIfc:qdTHQ0bfyUQ:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CSharperImage?i=KxUYu3-RIfc:qdTHQ0bfyUQ:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/CSharperImage?a=KxUYu3-RIfc:qdTHQ0bfyUQ:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CSharperImage?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/CSharperImage?a=KxUYu3-RIfc:qdTHQ0bfyUQ:I9og5sOYxJI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CSharperImage?d=I9og5sOYxJI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/CSharperImage/~4/KxUYu3-RIfc" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://csharperimage.jeremylikness.com/feeds/3101066328428581981/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://csharperimage.jeremylikness.com/2010/03/animations-and-view-models.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8944256652433533647/posts/default/3101066328428581981?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8944256652433533647/posts/default/3101066328428581981?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/CSharperImage/~3/KxUYu3-RIfc/animations-and-view-models.html" title="Animations and View Models: IAnimationDelegate" /><author><name>Jeremy Likness</name><uri>http://www.blogger.com/profile/18407945801671553594</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="05667915713066003387" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://csharperimage.jeremylikness.com/2010/03/animations-and-view-models.html</feedburner:origLink></entry><entry gd:etag="W/&quot;A04CQX48cSp7ImA9WxBUFEo.&quot;"><id>tag:blogger.com,1999:blog-8944256652433533647.post-4239047949059725813</id><published>2010-03-01T09:45:00.004-05:00</published><updated>2010-03-01T16:46:00.079-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-03-01T16:46:00.079-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="silveright 3" /><category scheme="http://www.blogger.com/atom/ns#" term="MEF" /><category scheme="http://www.blogger.com/atom/ns#" term="silverlight" /><category scheme="http://www.blogger.com/atom/ns#" term="prism" /><title>MEF instead of PRISM for Silverlight 3 Part 2 of 2: Region Management</title><content type="html">&lt;p&gt;&lt;a href="http://csharperimage.jeremylikness.com/2010/02/mef-instead-of-prism-for-silverlight-3.html" target="_blank"&gt;In my last post&lt;/a&gt;, I showed you how to dynamically load modules on demand using the latest MEF release in Silverlight 3. This post, I will take you through managing regions with MEF. This will enable us to have a 100% MEF-based solution in Silverlight 3 if the only pieces of PRISM we were using were the dynamic module loading and region management.
&lt;p&gt;&lt;a href="http://www.wintellect.com/CS/files/folders/sample_files/entry12237.aspx" target="_blank"&gt;Download the Source Code for this Post&lt;/a&gt;
&lt;p&gt;Quick note: technically, the Composite Application Guidance (PRISM) is more of a guidance than an actual library. The library that is often used is the reference library for the guidance. I only mention this because in using the concept of the region manager and views, technically we are implementing the PRISM concept here and using CAG, we're just using MEF as the engine instead of the included reference library.
&lt;p&gt;OK, let's get going ...
&lt;p&gt;The first thing I did this time around was to rip out all of the &lt;code&gt;IModuleInitialization&lt;/code&gt; pieces. They aren't needed because MEF will initialize what we need, as it's loaded. I destroyed the classes in the modules (it was good to see them load, anyway) and updated the navigation class to look like this:
&lt;pre class="brush: csharp;"&gt;
[Export(typeof(INavigation))]
public class ViewNavigator : INavigation 
{        
    [Import]
    public ICatalogService CatalogService { get; set; }
    
    private readonly Dictionary&amp;lt;ViewType, string&gt; _viewMap =
        new Dictionary&amp;lt;ViewType, string&gt;
            {
                { ViewType.MainView, "DynamicModule.xap" },
                { ViewType.SecondView, "SecondDynamicModule.cs.xap" }
            };   

    private readonly List&amp;lt;string&gt; _downloadedModules = new List&amp;lt;string&gt;();
                                                                   
    public void NavigateToView(ViewType view)
    {
        if (!_downloadedModules.Contains(_viewMap[view]))
        {
            var catalog = new DeploymentCatalog(_viewMap[view]);
            CatalogService.Add(catalog);
            catalog.DownloadAsync();
            _downloadedModules.Add(_viewMap[view]);
        }
    }           
}
&lt;/pre&gt;
&lt;p&gt;Thanks to &lt;a href="http://blogs.msdn.com/gblock/" target="_blank"&gt;Glenn Block&lt;/a&gt; for pointing out the excellent sample that comes included with the MEF bits (the deployment sample) ... this shows a different way of abstracting even the XAP file from the action of loading the catalog. In this case, I'm assuming I have prior knowledge of the controls and want to make my application more official by loading them dynamically as the user selects them.
&lt;p&gt;So, now we've re-factored. That's a lot cleaner! Next, I want strongly-typed regions. I created a new project just for the regions, and added this class to define the enumeration:
&lt;pre class="brush: csharp;"&gt;
public enum ViewRegion
{
    MainRegion,
    SubRegion 
}

public static class ViewRegionExtensions
{
    private static readonly List&amp;lt;ViewRegion&gt; _regions = new List&amp;lt;ViewRegion&gt; { ViewRegion.MainRegion, ViewRegion.SubRegion };       

    public static ViewRegion AsViewRegion(this string regionName)
    {
        foreach(var region in _regions)
        {
            if (regionName.Equals(region.ToString(), StringComparison.InvariantCultureIgnoreCase))
            {
                return region;
            }
        }
        return ViewRegion.MainRegion; 
    }
}
&lt;/pre&gt;
&lt;p&gt;Unfortunately, I don't believe the Silverlight version of the &lt;code&gt;Enum&lt;/code&gt; class allows you to enumerate the values of an enumeration. Therefore, I'm simply providing a static class to hold those and putting it next to the enum so it's easy to remember for maintenance. I also added an extension method that allows me to take a string and do &lt;code&gt;AsViewRegion()&lt;/code&gt; to convert it to the enum.
&lt;p&gt;In order to make the enum appear in XAML, we need to give Silverlight a hint that tells it how to convert from the string we'll key in the XAML to an actual enum we use in code. Here is the type converter, it basically says it only knows how to convert from strings, and uses the extension method to cast the string when called:
&lt;pre class="brush: csharp;"&gt;
public class ViewRegionConverter : TypeConverter 
{        
    public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
    {
        return sourceType.Equals(typeof (string));
    }

    public override object ConvertFrom(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value)
    {
        return ((string) value).AsViewRegion();
    }
}
&lt;/pre&gt;
&lt;p&gt;Now we can create our behavior. The behavior is an attached property we'll use to tag a container as a region. Eventually this can become complex as we support lists and content controls, but for the sake of this blog series I'm keeping it simple and limiting our containers to panels. Panels all have children, so it is easy to add an item to the children. The behavior will simply keep a static dictionary that maps the view region to the panel it was tagged to, and exposes a method that lets us request the panel for a view region. Here it is: 
&lt;pre class="brush: csharp;"&gt;
public static class RegionBehavior
{
    private static readonly Dictionary&amp;lt;ViewRegion, Panel&gt; _regions = new Dictionary&amp;lt;ViewRegion, Panel&gt;();
    
    public static readonly DependencyProperty RegionNameProperty = DependencyProperty.RegisterAttached(
        "RegionName",
        typeof (ViewRegion),
        typeof (RegionBehavior),
        new PropertyMetadata(ViewRegion.MainRegion, null));

    public static ViewRegion GetRegionName(DependencyObject obj)
    {
        return (ViewRegion) obj.GetValue(RegionNameProperty);
    }

    [TypeConverter(typeof(ViewRegionConverter))]
    public static void SetRegionName(DependencyObject obj, ViewRegion value)
    {
        obj.SetValue(RegionNameProperty, value);
        var panel = obj as Panel;
        if (panel != null)
        {
            _regions.Add(value, panel);
        }
    }
   
    public static Panel GetPanelForRegion(ViewRegion region)
    {
        return _regions[region];
    }

}
&lt;/pre&gt;
&lt;p&gt;Notice the type converter hint I give the setter. That lets the XAML know how to convert. In fact, this will even give us intellisense in the XAML, so it knows what the valid enumerations are! Now I can go into my main shell and create my first region (the intellisense quickly gave me a list to choose from ... right now there are only two choices!) 
&lt;pre class="brush: xml;"&gt;
&amp;lt;StackPanel Orientation="Vertical" Grid.Row="2" Regions:RegionBehavior.RegionName="MainRegion"/&gt;
&lt;/pre&gt;
&lt;p&gt;We can debug at this point and see that indeed the panel is registered with the dictionary with the behavior, so we're set on that front. Now we need to get our views into the region. We're still in the special "Regions" project and namespace. For now, I'm simply going to export type &lt;code&gt;UserControl&lt;/code&gt; for my view, and specify the region with an attribute. In MEF, we can create a strongly typed attribute for metadata: 
&lt;pre class="brush: csharp;"&gt;
[MetadataAttribute]
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
public class TargetRegionAttribute : ExportAttribute 
{        
    public TargetRegionAttribute() : base(typeof(UserControl))
    {
        
    }

    public ViewRegion Region { get; set; }
}
&lt;/pre&gt;
&lt;p&gt;So the type is UserControl but we can specify a region in the meta data. Now I can add a view to my dynamic module. I'm also specifying a region here for a nested view. 
&lt;pre class="brush: xml;"&gt;
&amp;lt;UserControl x:Class="DynamicModule.View"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:Regions="clr-namespace:RegionsWithMEF.Regions;assembly=RegionsWithMEF.Regions" 
    &gt;
    &amp;lt;Grid x:Name="LayoutRoot" Background="White"&gt;
        &amp;lt;Grid.ColumnDefinitions&gt;
            &amp;lt;ColumnDefinition Width="1*"/&gt;
            &amp;lt;ColumnDefinition Width="1*"/&gt;
        &amp;lt;/Grid.ColumnDefinitions&gt;
        &amp;lt;TextBlock Grid.Column="0" Text="Left Column of Outer View"/&gt;
        &amp;lt;StackPanel Grid.Column="1" Orientation="Vertical" Regions:RegionBehavior.RegionName="SubRegion"&gt;
            &amp;lt;TextBlock Text="Right Column of Outer View"/&gt;
        &amp;lt;/StackPanel&gt;
    &amp;lt;/Grid&gt;
&amp;lt;/UserControl&gt;
&lt;/pre&gt;
&lt;p&gt;We then tag the view for export with our custom attribute, like this: 
&lt;pre class="brush: csharp;"&gt;
[TargetRegion(Region=ViewRegion.MainRegion)]
public partial class View
{
    public View()
    {
        InitializeComponent();
    }
}
&lt;/pre&gt;
&lt;p&gt;Very easy and readable. I went ahead and added another control for the second view, and tagged it to the "sub region" view. 
&lt;p&gt;Now we've got our custom attributes and exports, but we still need to glue it together. When the catalog is loaded, the views will be tagged as exports. We just need something to import them and we can then inspect the meta data and put them in their proper places. For this, I created the &lt;code&gt;RegionManager&lt;/code&gt;. 
&lt;p&gt;First, let me back up. We want to read our meta data, so I need an interface with read only properties to pull it in: 
&lt;pre class="brush: csharp;"&gt;
public interface ITargetRegionCapabilities
{
    ViewRegion Region { get;  }
}
&lt;/pre&gt;
&lt;p&gt;Great! Now I can define region manager. We'll use the &lt;code&gt;Lazy&lt;/code&gt; object so we can define the capabilities with the import and inspect the meta data. I put it into an observable collection and listen to the collection. When it fires, I inspect the data for new controls, and then route them to their region based on the meta data: 
&lt;pre class="brush: csharp;"&gt;
[Export]
public class RegionManager
{
    private readonly List&amp;lt;UserControl&gt; _controls = new List&amp;lt;UserControl&gt;();

    [ImportMany(AllowRecomposition = true)]
    public ObservableCollection&amp;lt;Lazy&amp;lt;UserControl, ITargetRegionCapabilities&gt;&gt; Controls { get; set; }

    public RegionManager()
    {
        Controls = new ObservableCollection&amp;lt;Lazy&amp;lt;UserControl, ITargetRegionCapabilities&gt;&gt;();
        Controls.CollectionChanged += Controls_CollectionChanged;
    }

    void Controls_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
    {
        if (e.NewItems != null)
        {
            foreach(var item in e.NewItems)
            {
                var controlInfo = item as Lazy&amp;lt;UserControl, ITargetRegionCapabilities&gt;;

                if (controlInfo != null)
                {
                    if (!_controls.Contains(controlInfo.Value))
                    {
                        ViewRegion region = controlInfo.Metadata.Region;
                        Panel panel = RegionBehavior.GetPanelForRegion(region);
                        panel.Children.Add(controlInfo.Value);
                        _controls.Add(controlInfo.Value);
                    }
                }
            }
        }
    }
}
&lt;/pre&gt;
&lt;p&gt;&lt;b&gt;Note:&lt;/b&gt; if you are wondering why I use a list and an observable collection, it's because with recomposition, MEF is free to rebuild the entire list. I need to know specifically what changed and the "new items" might include older items that were recomposed. So the internal list allows me to keep track of what I've processed while I can parse out the newer items. With custom items you'll want to make sure you have a good implementation of &lt;code&gt;Equals&lt;/code&gt; and &lt;code&gt;GetHashCode&lt;/code&gt;, and if you have items that will go out of focus and disappear, you'll want to switch the internal list to a list of &lt;code&gt;WeakReference&lt;/code&gt; instead.
&lt;p&gt;That's it! The last step is to make sure that the region manager participates in the entire chain of imports and exports. I could wire it up in the container, but I know the shell view model is the top of the hierarchy, so to speak, so I'll just import the region manager directly. I haven't interfaced it because it doesn't expose any methods or properties: all of the work is internal and interfaces with the static dictionary we put into our behavior.
&lt;pre class="brush: csharp;"&gt;
[Import]
public RegionManager Manager { get; set; }
&lt;/pre&gt;
&lt;p&gt;OK, let's fire it up. I made a short video to show you the results. 
&lt;object id="scPlayer" width="616" height="632"&gt; &lt;param name="movie" value="http://content.screencast.com/users/JeremyLikness/folders/Jing/media/6cdd4675-0ecb-4499-8c84-432d1999dfc8/jingswfplayer.swf"&gt;&lt;/param&gt; &lt;param name="quality" value="high"&gt;&lt;/param&gt; &lt;param name="bgcolor" value="#FFFFFF"&gt;&lt;/param&gt; &lt;param name="flashVars" value="thumb=http://content.screencast.com/users/JeremyLikness/folders/Jing/media/6cdd4675-0ecb-4499-8c84-432d1999dfc8/FirstFrame.jpg&amp;containerwidth=616&amp;containerheight=632&amp;content=http://content.screencast.com/users/JeremyLikness/folders/Jing/media/6cdd4675-0ecb-4499-8c84-432d1999dfc8/2010-02-25_1940.swf"&gt;&lt;/param&gt; &lt;param name="allowFullScreen" value="true"&gt;&lt;/param&gt; &lt;param name="scale" value="showall"&gt;&lt;/param&gt; &lt;param name="allowScriptAccess" value="always"&gt;&lt;/param&gt; &lt;param name="base" value="http://content.screencast.com/users/JeremyLikness/folders/Jing/media/6cdd4675-0ecb-4499-8c84-432d1999dfc8/"&gt;&lt;/param&gt;  &lt;embed src="http://content.screencast.com/users/JeremyLikness/folders/Jing/media/6cdd4675-0ecb-4499-8c84-432d1999dfc8/jingswfplayer.swf" quality="high" bgcolor="#FFFFFF" width="616" height="632" type="application/x-shockwave-flash" allowScriptAccess="always" flashVars="thumb=http://content.screencast.com/users/JeremyLikness/folders/Jing/media/6cdd4675-0ecb-4499-8c84-432d1999dfc8/FirstFrame.jpg&amp;containerwidth=616&amp;containerheight=632&amp;content=http://content.screencast.com/users/JeremyLikness/folders/Jing/media/6cdd4675-0ecb-4499-8c84-432d1999dfc8/2010-02-25_1940.swf" allowFullScreen="true" base="http://content.screencast.com/users/JeremyLikness/folders/Jing/media/6cdd4675-0ecb-4499-8c84-432d1999dfc8/" scale="showall"&gt;&lt;/embed&gt; &lt;/object&gt;
&lt;br/&gt;
&lt;br/&gt;
&lt;p&gt;&lt;a href="http://www.wintellect.com/CS/files/folders/sample_files/entry12237.aspx" target="_blank"&gt;Download the Source Code for this Post&lt;/a&gt;
&lt;p&gt;Watch a great video tutorial covering dynamic modules with Glenn Block on Channel 9: &lt;a href="http://channel9.msdn.com/shows/SilverlightTV/Silverlight-TV-11-Dynamically-Loading-XAPs-with-MEF/" target="_blank"&gt;Dynamically Loading XAPs with MEF&lt;/a&gt;.
&lt;p&gt;&lt;a href="http://jeremylikness.com/" title="Jeremy Likness"&gt;&lt;img border="0" src="http://jeremylikness.com/signature.gif" alt="Jeremy Likness" title="Jeremy Likness"/&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8944256652433533647-4239047949059725813?l=csharperimage.jeremylikness.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/CSharperImage?a=GP2R3d3pKWs:qanaDFHjM4o:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CSharperImage?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/CSharperImage?a=GP2R3d3pKWs:qanaDFHjM4o:YwkR-u9nhCs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CSharperImage?d=YwkR-u9nhCs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/CSharperImage?a=GP2R3d3pKWs:qanaDFHjM4o:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CSharperImage?i=GP2R3d3pKWs:qanaDFHjM4o:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/CSharperImage?a=GP2R3d3pKWs:qanaDFHjM4o:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CSharperImage?i=GP2R3d3pKWs:qanaDFHjM4o:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/CSharperImage?a=GP2R3d3pKWs:qanaDFHjM4o:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CSharperImage?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/CSharperImage?a=GP2R3d3pKWs:qanaDFHjM4o:I9og5sOYxJI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CSharperImage?d=I9og5sOYxJI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/CSharperImage/~4/GP2R3d3pKWs" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://csharperimage.jeremylikness.com/feeds/4239047949059725813/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://csharperimage.jeremylikness.com/2010/03/mef-instead-of-prism-for-silverlight-3.html#comment-form" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8944256652433533647/posts/default/4239047949059725813?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8944256652433533647/posts/default/4239047949059725813?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/CSharperImage/~3/GP2R3d3pKWs/mef-instead-of-prism-for-silverlight-3.html" title="MEF instead of PRISM for Silverlight 3 Part 2 of 2: Region Management" /><author><name>Jeremy Likness</name><uri>http://www.blogger.com/profile/18407945801671553594</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="05667915713066003387" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">2</thr:total><feedburner:origLink>http://csharperimage.jeremylikness.com/2010/03/mef-instead-of-prism-for-silverlight-3.html</feedburner:origLink></entry><entry gd:etag="W/&quot;C0MMQnoyeSp7ImA9WxBUFEs.&quot;"><id>tag:blogger.com,1999:blog-8944256652433533647.post-1544076315430839838</id><published>2010-02-26T13:15:00.002-05:00</published><updated>2010-03-01T11:38:03.491-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-03-01T11:38:03.491-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Managed Extensibility Framework" /><category scheme="http://www.blogger.com/atom/ns#" term="MEF" /><category scheme="http://www.blogger.com/atom/ns#" term="silverlight" /><category scheme="http://www.blogger.com/atom/ns#" term="silverlight 3" /><category scheme="http://www.blogger.com/atom/ns#" term="prism" /><category scheme="http://www.blogger.com/atom/ns#" term="dynamic modules" /><title>MEF instead of PRISM for Silverlight 3 Part 1 of 2: Dynamic Module Loading</title><content type="html">&lt;p&gt;Recently I've been having lots of conversations about the &lt;a href="http://mef.codeplex.com/" target="_blank"&gt;Managed Extensibility Framework (MEF)&lt;/a&gt;, the &lt;a href="http://compositewpf.codeplex.com/" target="_blank"&gt;Composite Application Library (CAL or PRISM)&lt;/a&gt;, and how they relate. One point of confusion that many people has comes when they try to force the two solutions to work together. In a recent conversation, I mentioned that PRISM has some great features, but that if you are only using it for dynamic module loading and view management, MEF should do fine. Then I promised to post a blog with a reference project ... and here it is. 
&lt;p&gt;&lt;a href="http://www.wintellect.com/CS/files/folders/sample_files/entry12189.aspx" target="_blank"&gt;Download the source for this project&lt;/a&gt;
&lt;p&gt;First, let me share that I love PRISM and have been working with it in almost all of my projects for the past year. My Wintellect colleague Rik Robinson has an excellent article on PRISM &lt;a href="http://www.devproconnections.com/article/silverlight-development/Introduction-to-Using-Prism-with-Silverlight-3.aspx" target="_blank"&gt;you can read here&lt;/a&gt;. You can also scan this blog &lt;a href="http://csharperimage.jeremylikness.com/search/label/prism" target="_blank"&gt;with the PRISM tag&lt;/a&gt;. However, I've started to really enjoy working with MEF and believe it is quickly becoming the solution of choice for composite Silverlight applications ... especially with it's inclusion in the upcoming 4.0 release. In these 2 posts I'll show you how to tackle dynamic module loading and region management using exclusively MEF instead of PRISM.
&lt;p&gt;I'm working with the preview 9 of the bits and showing what can be done in the current production release of Silverlight which is version 3. To start with, I simply create a new Silverlight Application. I add a folder called "MEF" and throw the bits in there, which is really two DLLs: &lt;code&gt;System.ComponentModel.Composition&lt;/code&gt; and &lt;code&gt;System.ComponentModel.Composition.Initialization&lt;/code&gt;. I reference those.
&lt;p&gt;&lt;b&gt;The "Bootstrapper" in MEF&lt;/b&gt;
&lt;p&gt;Next I create a new empty user control called &lt;code&gt;Shell.xaml&lt;/code&gt; (sound familiar?) that just has a grid and a text block so I know it's there. If you are familiar with PRISM, you are familiar with the concept of the Bootstrapper class to wire everything up. With MEF, we'll do it a little different. First, I go inside the shell and simply decorate it with the "export" attribute:
&lt;pre class="brush: csharp;"&gt;
[Export]
public partial class Shell
{
    public Shell()
    {
        InitializeComponent();
    }
}
&lt;/pre&gt;
&lt;p&gt;Next, I go into my main application class (&lt;code&gt;App.cs&lt;/code&gt;) and add a property to import the Shell, like this: 
&lt;pre class="brush: csharp;"&gt;
...
[Import]
public Shell RootView { get; set; }
...
&lt;/pre&gt;
&lt;p&gt;Finally, in the application start-up method, instead of newing up a "main page" which no longer exists, I simply ask MEF to satisfy my import of the shell, then assign it to the root visual: 
&lt;pre class="brush: csharp;"&gt;
private void Application_Startup(object sender, StartupEventArgs e)
{
    CompositionInitializer.SatisfyImports(this);
    RootVisual = RootView;
}
&lt;/pre&gt;
&lt;p&gt;That's it! When I hit F5 I see the text I placed in the shell, so I know it's being placed in the root visual. We're good to go! I'm going to tackle dynamic loading first, then look at region management. I'll need some buttons to trigger the loading, so we'll want to roll a command behavior. This is one of the nice things that comes with PRISM (the commands), but let's see how easy or difficult it is to roll our own.
&lt;p&gt;&lt;b&gt;Custom Commands&lt;/b&gt;
&lt;p&gt;&lt;a href="http://www.microsoft.com/expression/products/Blend_Overview.aspx" target="_blank"&gt;Microsoft Expression Blend&lt;/a&gt; provides a set of base triggers and behaviors that make it easy to add new functionality like commanding. If you don't have the full tool, don't despair - these are also included in the &lt;a href="http://www.microsoft.com/DOWNLOADS/details.aspx?FamilyID=f1ae9a30-4928-411d-970b-e682ab179e17&amp;displaylang=en" target="_blank"&gt;free SDK you can download&lt;/a&gt;. I'm including a reference to &lt;code&gt;System.Windows.Interactivity&lt;/code&gt;. 
&lt;p&gt;I want to do a trigger action. A trigger action allows me to act on any event, which I prefer over hard-coding just to a button click.
&lt;p&gt;Before I get ahead of myself, though, let's create our command. While Silverlight 3 doesn't have a built-in command object, it does provide the &lt;code&gt;ICommand&lt;/code&gt; interface. I'm going to do a partial implementation. I say "partial" because the interface allows for something to be passed to the command, and I'm simply raising the command and assuming null for the sake of this blog post:
&lt;pre class="brush: csharp;"&gt;
public class CommandAction : ICommand 
{
    private readonly Func&amp;lt;bool&gt; _canExecute;

    private readonly Action _execute; 

    public CommandAction(Action action, Func&amp;lt;bool&gt; canExecute)
    {
        _execute = action;
        _canExecute = canExecute;
    }

    public bool CanExecute(object parameter)
    {
        return _canExecute();
    }

    public void Execute(object parameter)
    {
        _execute();
    }

    public void RaiseCanExecuteChanged()
    {
        EventHandler handler = CanExecuteChanged;
        if (handler != null)
        {
            handler(this, EventArgs.Empty);
        }
    }

    public event EventHandler CanExecuteChanged;
}
&lt;/pre&gt;
&lt;p&gt;While I haven't looked at the code in PRISM, I assume this is very close to how they wire the &lt;code&gt;DelegateCommand&lt;/code&gt;. We hold a function that determines if the command is enabled, and an action to call when the command is invoked. Whoever creates the &lt;code&gt;CommandAction&lt;/code&gt; is responsible for passing those delegates in and raising "can execute changed" when appropriate. 
&lt;p&gt;Now I can start to work on the command behavior. Because of my unique command type, I'm just going to allow you to pass the name of the command on the data bound object and will dissect the rest. If you bind a view model with "ActionCommand" then I'll let you wire up it up that way. Because we're using MEF to bind our view models, my behavior will get wired well before the bindings happen. I'll need to know when the data context changes, so I build a data context helper. It basically uses dependency properties to listen to a "dummy"  binding for changes, then calls an action when the changes happen. It looks like this and is loosely based on a previous post I made on data context changed events: 
&lt;pre class="brush: csharp;"&gt;
public static class DataContextChangedHandler
{
    private const string INTERNAL_CONTEXT = "InternalDataContext";
    private const string CONTEXT_CHANGED = "DataContextChanged";

    public static readonly DependencyProperty InternalDataContextProperty =
        DependencyProperty.Register(INTERNAL_CONTEXT,
                                    typeof(Object),
                                    typeof(FrameworkElement),
                                    new PropertyMetadata(_DataContextChanged));

    public static readonly DependencyProperty DataContextChangedProperty =
        DependencyProperty.Register(CONTEXT_CHANGED,
                                    typeof(Action&amp;lt;Control&gt;),
                                    typeof(FrameworkElement),
                                    null);

    
    private static void _DataContextChanged(object sender, DependencyPropertyChangedEventArgs e)
    {
        var control = (Control)sender;
        var handler = (Action&amp;lt;Control&gt;) control.GetValue(DataContextChangedProperty);
        if (handler != null)
        {
            handler(control); 
        }
    }

    public static void Bind(Control control, Action&amp;lt;Control&gt; dataContextChanged)
    {
        control.SetBinding(InternalDataContextProperty, new Binding());
        control.SetValue(DataContextChangedProperty, dataContextChanged); 
    }
}

&lt;/pre&gt;
&lt;p&gt;In this case, I'm scoping specifically to a control, which is where I believe the lowest level of "is enabled" gets implemented for controls that can react to changes, so that makes sense for our behavior. When I call bind, I pass it a control and a delegate to call when that control's data context changes. Now we can build in our behavior: 
&lt;pre class="brush: csharp;"&gt;
public class CommandBehavior : TriggerAction&amp;lt;Control&gt;
{
    public static readonly DependencyProperty CommandBindingProperty = DependencyProperty.Register(
        "CommandBinding",
        typeof(string),
        typeof(CommandBehavior),
        null);

    public string CommandBinding
    {
        get { return (string)GetValue(CommandBindingProperty); }
        set { SetValue(CommandBindingProperty, value); }
    }

    private CommandAction _action; 

    protected override void OnAttached()
    {
        DataContextChangedHandler.Bind(AssociatedObject, obj=&gt;_ProcessCommand());
    }

    private void _ProcessCommand()
    {
        if (AssociatedObject != null)
        {

            var dataContext = AssociatedObject.DataContext;

            if (dataContext != null)
            {
                var property = dataContext.GetType().GetProperty(CommandBinding);
                if (property != null)
                {
                    var value = property.GetValue(dataContext, null);
                    if (value != null &amp;amp;&amp;amp; value is CommandAction)
                    {
                        _action = value as CommandAction;
                        AssociatedObject.IsEnabled = _action.CanExecute(null);
                        _action.CanExecuteChanged += (o, e) =&gt; AssociatedObject.IsEnabled = _action.CanExecute(null);

                    }
                }
            }
        }
    }

    protected override void Invoke(object parameter)
    {
        if (_action != null &amp;amp;&amp;amp; _action.CanExecute(null))
        {
            _action.Execute(null);
        }
    }      
}
&lt;/pre&gt;
&lt;p&gt;OK, let's step through it. I'm using the &lt;code&gt;System.Windows.Interactivity&lt;/code&gt; namespace to define a trigger action, which can be bound to any event. I'm scoping it to a control. When my behavior is attached, I'm binding to the data context changed event. I ask it to call my method to process the command when the data context changes (presumably to bind our command). When that fires, I grab the property that is named in my behavior from the data context, cast it to a command, and wire it up to automatically change whether the host control is enabled based on the &lt;code&gt;CanExecute&lt;/code&gt; method of the control. When my behavior is invoked, I check this again and then execute.
&lt;p&gt;&lt;b&gt;ViewModel Glue&lt;/b&gt;
&lt;p&gt;There's been a lot of discussion (including in this blog) around how to glue the view model to the view. I personally like to keep it simple and straightforward. Here's a view model stubbed out for the shell that lets me click a button to dynamically load a view. I want to disable the button once clicked so they don't load the view more than once.
&lt;pre class="brush: csharp;"&gt;
[Export]
public class ShellViewModel
{
    public ShellViewModel()
    {
        ViewEnabled = true;
        ViewClick = new CommandAction(_ViewRequested,
                                      () =&gt; ViewEnabled);
    }

    private bool _viewEnabled;

    public bool ViewEnabled
    {
        get { return _viewEnabled; }
        set
        {
            _viewEnabled = value;
            
            if (ViewClick != null)
            {
                ViewClick.RaiseCanExecuteChanged();
            }
        }
    }

    public CommandAction ViewClick { get; set; }

    private void _ViewRequested()
    {
        ViewEnabled = false;
    }
}
&lt;/pre&gt;
&lt;p&gt;Note I use a property to determine if the command is enabled, then call a method to process it when fired. We'll add more to that method in a minute. Let's get this into our shell. Because the shell is wired up in the application through the initializer, there is no need to initialize or compose again. This is done recursively. So, let me add a little bit to my shell: 
&lt;pre class="brush: xml;"&gt;
&amp;lt;UserControl x:Class="RegionsWithMEF.Shell"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:interactivity="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
    xmlns:command="clr-namespace:RegionsWithMEF.Common.Command;assembly=RegionsWithMEF.Common"
    &gt;
    &amp;lt;Grid x:Name="LayoutRoot" Background="White"&gt;
        &amp;lt;Grid.RowDefinitions&gt;
            &amp;lt;RowDefinition Height="Auto"/&gt;
            &amp;lt;RowDefinition Height="Auto"/&gt;
            &amp;lt;RowDefinition/&gt;
        &amp;lt;/Grid.RowDefinitions&gt;
        &amp;lt;TextBlock Text="Main MEF Shell"/&gt;
        &amp;lt;Button Content="Load Dynamic View into Region" Width="Auto" Height="Auto" Grid.Row="1"&gt;
            &amp;lt;interactivity:Interaction.Triggers&gt;
                &amp;lt;interactivity:EventTrigger EventName="Click"&gt;
                    &amp;lt;command:CommandBehavior CommandBinding="ViewClick"/&gt;
                &amp;lt;/interactivity:EventTrigger&gt;
            &amp;lt;/interactivity:Interaction.Triggers&gt;
        &amp;lt;/Button&gt;
    &amp;lt;/Grid&gt;
&amp;lt;/UserControl&gt;
&lt;/pre&gt;
&lt;p&gt;Notice how I use the interactivity namespace to define a trigger for the button. The trigger is for the "click" event, but the way we built the behavior, it can easily fire based on other events as well. I bring in my command behavior, and point it to the "ViewClick" property on my view model. A more advanced implementation would turn that into a full blown binding property and allow binding syntax but for now we'll stick with the simple property name. 
&lt;p&gt;In the code behind, I wire in my view model:
&lt;pre class="brush: csharp;"&gt;
[Import]
public ShellViewModel ViewModel
{
    get { return LayoutRoot.DataContext as ShellViewModel; }
    set { LayoutRoot.DataContext = value; }
}
&lt;/pre&gt;
&lt;p&gt;That's it! I run the project to test it, and get a nice text block with a button. When I click the button, it disables immediately. Now let's tackle that dynamic view!
&lt;p&gt;&lt;b&gt;Controlling the Catalog and Container&lt;/b&gt;
&lt;p&gt;We want to dynamically load some modules, but first we'll need to tweak our container. By default, MEF is going to create a container in our main application and compose parts to it. Unfortunately, that means when we load other modules/xap files, they won't have access to the container! We need to fix this. 
&lt;p&gt;First, I'll create a service to expose an &lt;code&gt;AggregateCatalog&lt;/code&gt; that I can add other catalogs to. I want to get the catalog and add parts to it: 
&lt;pre class="brush: csharp;"&gt;
public interface ICatalogService
{
    void Add(ComposablePartCatalog catalog);

    AggregateCatalog GetCatalog();

}
&lt;/pre&gt;
&lt;p&gt;Next, I will implement this by creating an aggregate catalog. I'm going to assume when the service is created that we want to include the currently loaded assemblies. This assumption may be wrong and down the road we might inject the catalog, but for now we'll iterate the current deployment (set of running assemblies) and pull them in to parse into our catalog: 
&lt;pre class="brush: csharp;"&gt;
public class CatalogService : ICatalogService
{
    private read-only AggregateCatalog _catalog = new AggregateCatalog();

    public CatalogService()
    {
        foreach (AssemblyPart ap in Deployment.Current.Parts)
        {
            StreamResourceInfo sri = Application.GetResourceStream(new Uri(ap.Source, UriKind.Relative));

            if (sri != null)
            {
                Assembly assembly = ap.Load(sri.Stream);
                _catalog.Catalogs.Add(new AssemblyCatalog(assembly));
            }
        }
    }    

    public void Add(ComposablePartCatalog catalog)
    {
        _catalog.Catalogs.Add(catalog);
    }

    public AggregateCatalog GetCatalog()
    {
        return _catalog; 
    }
}
&lt;/pre&gt;
&lt;p&gt;&lt;b&gt;Addendum:&lt;/b&gt; thanks to Glenn Block for pointing out a fix here. I am manually loading the assemblies, and this is no longer necessary. I kept the block here to be consistent with the code download, but here is the "fix" you can make it easily load the existing assemblies:
&lt;pre class="brush: csharp;"&gt;
public class CatalogService : ICatalogService
{
    private read-only AggregateCatalog _catalog = new AggregateCatalog();

    public CatalogService()
    {
       // empty deployment catalog parses existing XAP by default
       Add(new DeploymentCatalog());
    }    

    public void Add(ComposablePartCatalog catalog)
    {
        _catalog.Catalogs.Add(catalog);
    }

    public AggregateCatalog GetCatalog()
    {
        return _catalog; 
    }
}
&lt;/pre&gt;

&lt;p&gt;Now we just need to tweak the main application. We'll instantiate the service, then tell it how to expose itself (sounds weird, I know, but when I bring in a module, I want it to be able to add itself to the aggregate catalog, so the catalog service must be exported). We'll let MEF know we want to use this specific container moving forward, and then we'll initialize as before. The new method looks like this:
&lt;pre class="brush: csharp;"&gt;
private void Application_Startup(object sender, StartupEventArgs e)
{
    ICatalogService service = new CatalogService();
    var container = new CompositionContainer(service.GetCatalog());
    container.ComposeExportedValue(service);
    CompositionHost.Initialize(container); 
    CompositionInitializer.SatisfyImports(this);
    RootVisual = RootView;
}
&lt;/pre&gt;
&lt;p&gt;&lt;b&gt;Dynamic Loading of Modules&lt;/b&gt;
&lt;p&gt;MEF Preview 9 comes with a deployment catalog that gives us what we need. First, I want to hide the implementation details of loading a view. I'll create an enumeration of views that are available (in this case, only one) and an interface to call when I'm ready to navigate to a view. 
&lt;p&gt;For now, I want to just grab the view and verify it's loaded. Then we'll wrap up for today and tackle the region management in the next post.
&lt;p&gt;I extended my shell view model to anticipate two views. In fact, to make the example more interesting, I will load the second view into the first view. Therefore, the second button is only enabled once the first button has been clicked, like this: 
&lt;pre class="brush: csharp;"&gt;
SecondViewClick = new CommandAction(
    _SecondViewRequested,
    () =&gt; !ViewEnabled &amp;amp;&amp;amp; SecondViewEnabled);
&lt;/pre&gt;
&lt;p&gt;Here's our views:
&lt;pre class="brush: csharp;"&gt;
public enum ViewType
{
    MainView,
    SecondView
}
&lt;/pre&gt;
&lt;p&gt;And the interface for our view navigation: 
&lt;pre class="brush: csharp;"&gt;
public interface INavigation
{
    void NavigateToView(ViewType view);
}
&lt;/pre&gt;
&lt;p&gt;So now I can go back to my view model and wire in the navigation, as well as make the call. Here is the modified code:
&lt;pre class="brush: csharp;"&gt;
[Import]
public INavigation Navigation { get; set; }

private void _ViewRequested()
{
    ViewEnabled = false;
    Navigation.NavigateToView(ViewType.MainView);
}

private void _SecondViewRequested()
{
    SecondViewEnabled = false;
    Navigation.NavigateToView(ViewType.SecondView);
}
&lt;/pre&gt;
&lt;p&gt;Now I will add my modules. As I mentioned, I just want them to load for now. I can deal with the views later. So I create two more Silverlight applications in my solution called "DynamicModule" and then "SecondDynamicModule.cs" ... yes, the second is a typo because I thought I was adding a class, and was too lazy to re-factor it. So there. I imagine when I load a module I'll want it to do perform some "introductory" functions, so let's define an initialization interface:
&lt;pre class="brush: csharp;"&gt;
public interface IModuleInitializer
{
    void InitModule();
}
&lt;/pre&gt;
&lt;p&gt;In both of my dynamic modules, I add a class that implements this interface and export it. I gave them different names to show it's the interface the matters, but here's what one looks like (right now I just return, but I can set the breakpoint there to test when and if the module is loaded and called):
&lt;pre class="brush: csharp;"&gt;
[Export(typeof(IModuleInitializer))]
public class ModuleInitializer : IModuleInitializer
{
    public void InitModule()
    {
        return; 
    }              
}
&lt;/pre&gt;
&lt;p&gt;OK, now I can implement my &lt;code&gt;INavigation&lt;/code&gt; interface. We're going to do two things. First, we'll map views to modules so we can dynamically load them using the &lt;code&gt;DeploymentCatalog&lt;/code&gt;. Second, we'll import a collection of module initializers. This is the super-cool feature of MEF: recomposition. When we load the module and put it in our main catalog, it will recompose. This should fire a change to our collection of initializers. We can take the new items and call them, and we'll be initialized. Here's what it looks like:
&lt;pre class="brush: csharp;"&gt;
[Export(typeof(INavigation))]
public class ViewNavigator : INavigation 
{        
    [Import]
    public ICatalogService CatalogService { get; set; }

    [ImportMany(AllowRecomposition = true)]
    public ObservableCollection&amp;lt;IModuleInitializer&gt; Initializers { get; set; }

  private readonly List&amp;lt;IModuleInitializer&gt; _modules = new List&amp;lt;IModuleInitializer&gt;();

    private readonly Dictionary&amp;lt;ViewType, string&gt; _viewMap =
        new Dictionary&amp;lt;ViewType, string&gt;
            {
                { ViewType.MainView, "DynamicModule.xap" },
                { ViewType.SecondView, "SecondDynamicModule.cs.xap" }
            };   

    private readonly List&amp;lt;string&gt; _downloadedModules = new List&amp;lt;string&gt;();

    public ViewNavigator()
    {
        Initializers = new ObservableCollection&amp;lt;IModuleInitializer&gt;();
        Initializers.CollectionChanged += Initializers_CollectionChanged;
    }
    
    void Initializers_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
    {
        if (e.NewItems != null)
        {
            foreach(var item in e.NewItems)
            {
                var initializer = item as IModuleInitializer; 
                if (initializer != null)
                {
                    if (!_modules.Contains(initializer))
                    {
                        initializer.InitModule();
                        _modules.Add(initializer);
                    }
                }
            }
        }
    }                                                                                              
  
    public void NavigateToView(ViewType view)
    {
        if (!_downloadedModules.Contains(_viewMap[view]))
        {
            var catalog = new DeploymentCatalog(_viewMap[view]);
            CatalogService.Add(catalog);
            catalog.DownloadAsync();
            _downloadedModules.Add(_viewMap[view]);
        }
    }               
}
&lt;/pre&gt;
&lt;p&gt;Right now the navigate to view isn't very flexible. It loads the catalogs but doesn't do anything with the views. I'm also not handling errors when the XAP isn't loaded. We are tracking modules and xaps that were already loaded, so we don't load them again or re-initialize the module. We'll get to that in the next installment when we wire in regions. For now, we can put a breakpoint in the "return" of the init modules, fire up the application, and click our buttons to watch them get dynamically loaded into the system (you can use &lt;a href="http://fiddler2.com/" target="_blank"&gt;Fiddler&lt;/a&gt; to watch the packets come over the wire). Pretty exciting! 
&lt;p&gt;In the next installment, I'll show you how MEF will handle region management.
&lt;p&gt;&lt;a href="http://www.wintellect.com/CS/files/folders/sample_files/entry12189.aspx" target="_blank"&gt;Download the source for this project&lt;/a&gt;
&lt;p&gt;&lt;a href="http://jeremylikness.com/" title="Jeremy Likness"&gt;&lt;img border="0" src="http://jeremylikness.com/signature.gif" alt="Jeremy Likness" title="Jeremy Likness"/&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8944256652433533647-1544076315430839838?l=csharperimage.jeremylikness.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/CSharperImage?a=jgipFwKriOE:TKHb47jglOs:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CSharperImage?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/CSharperImage?a=jgipFwKriOE:TKHb47jglOs:YwkR-u9nhCs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CSharperImage?d=YwkR-u9nhCs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/CSharperImage?a=jgipFwKriOE:TKHb47jglOs:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CSharperImage?i=jgipFwKriOE:TKHb47jglOs:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/CSharperImage?a=jgipFwKriOE:TKHb47jglOs:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CSharperImage?i=jgipFwKriOE:TKHb47jglOs:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/CSharperImage?a=jgipFwKriOE:TKHb47jglOs:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CSharperImage?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/CSharperImage?a=jgipFwKriOE:TKHb47jglOs:I9og5sOYxJI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CSharperImage?d=I9og5sOYxJI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/CSharperImage/~4/jgipFwKriOE" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://csharperimage.jeremylikness.com/feeds/1544076315430839838/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://csharperimage.jeremylikness.com/2010/02/mef-instead-of-prism-for-silverlight-3.html#comment-form" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8944256652433533647/posts/default/1544076315430839838?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8944256652433533647/posts/default/1544076315430839838?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/CSharperImage/~3/jgipFwKriOE/mef-instead-of-prism-for-silverlight-3.html" title="MEF instead of PRISM for Silverlight 3 Part 1 of 2: Dynamic Module Loading" /><author><name>Jeremy Likness</name><uri>http://www.blogger.com/profile/18407945801671553594</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="05667915713066003387" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">1</thr:total><feedburner:origLink>http://csharperimage.jeremylikness.com/2010/02/mef-instead-of-prism-for-silverlight-3.html</feedburner:origLink></entry><entry gd:etag="W/&quot;AkIGSHo7fSp7ImA9WxBUEU0.&quot;"><id>tag:blogger.com,1999:blog-8944256652433533647.post-5108722851039396553</id><published>2010-02-25T09:35:00.000-05:00</published><updated>2010-02-25T09:35:29.405-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-02-25T09:35:29.405-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="silverlight" /><category scheme="http://www.blogger.com/atom/ns#" term="silverlight unit test" /><category scheme="http://www.blogger.com/atom/ns#" term="prism" /><category scheme="http://www.blogger.com/atom/ns#" term="olympics" /><title>Vancouver Olympics - How'd We Do That?</title><content type="html">&lt;p&gt;The &lt;a href="http://team.silverlight.net/" target="_blank"&gt;Silverlight team&lt;/a&gt; recently posted a blog entry entitled "&lt;a href="http://team.silverlight.net/customer-evidence/vancouver-olympics-ndash-how-rsquo-d-we-do-that/" target="_blank"&gt;Vancouver Olympics - How'd we do That?&lt;/a&gt;" in which they detailed the massive effort across multiple partners to pull together the on-line solution for streaming HD videos, both live and on demand. 
&lt;p&gt;This was an exciting post for &lt;a href="http://www.wintellect.com/" target="_blank"&gt;Wintellect&lt;/a&gt; and me because it detailed the effort we contributed to making the project a success. What's more important to me for the Silverlight community, however, is that you don't overlook the key detail they posted on the blog:
&lt;blockquote&gt;Development of a Silverlight application to interface with the service agents via WCF. This tool allows Microsoft to quickly publish new configuration files (such as web.config and clientaccesspolicy.xml) to groups of servers, as well as dynamically manipulate configuration settings through a visual interface (for example, turning off compression on a remote smooth streaming server when required) on multiple remote servers at once.&lt;/blockquote&gt;
&lt;p&gt;This is important because as a Silverlight developer I am constantly bombarded with questions about how viable Silverlight is, if it is ready for the enterprise and what practical application it has for business. This is a specific example where it was the right tool for the right job. 
&lt;p&gt;I won't go into more details about the tool other than what Microsoft has publicly shared, but I wanted to emphasize that this is another example of how Silverlight helps to solve real world problems. When looking at the requirements for the health monitoring, we had several options for a solution. In this case, WPF wouldn't have worked because they would have had to remote into the environment in order to access the tool. However, using ASP.NET and JavaScript would have required jumping through some major hoops and use of heavy controls to correctly render the user interface they required. The tool essentially parses any XML-base configuration file and allows on-line navigation and updates to that document. While this would have been possible using script, it would have taken much longer and required an extended cycle of testing to stabilize. 
&lt;p&gt;Due to Silverlight's unique data-binding model and full LINQ to XML support, we were able to build a solution quickly and effectively. We were also able to use the unit testing framework to build hundreds of unit tests that helped ensure a stable, thorough, and well-tested solution. Again, using scripting would have required more complicated tools that simulated user-clicks, etc. With Silverlight, we can place controls on a test surface and simulate the click events to test everything from behaviors down to internal class methods.
&lt;p&gt;PRISM, or the Composite Application Library, was also crucial with the success of keeping the module light weight. There were literally dozens of functions the tool could provide but only a few might be used at any given time, so we separated the functions into independent modules that dynamically loaded as needed to provide a streamlined experience. 
&lt;p&gt;While I was excited to work on the project with my company, I am even more excited that it demonstrates yet again how Silverlight is the right tool, right here, right now for enterprise class applications. This is another "case study" to add to your arsenal as you answer questions about, "Is it ready?" or "Has it been done before." I believe the fact that it was so crucial both in the front end (with the live streaming experience) and back-end (with the management tools) for an incredible event like the Olympics really proves how mature and ready Silverlight is for business class applications.
&lt;p&gt;&lt;a href="http://jeremylikness.com/" title="Jeremy Likness"&gt;&lt;img border="0" src="http://jeremylikness.com/signature.gif" alt="Jeremy Likness" title="Jeremy Likness"/&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8944256652433533647-5108722851039396553?l=csharperimage.jeremylikness.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/CSharperImage?a=x3ARPjZmWFM:i6I2_VNd5aI:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CSharperImage?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/CSharperImage?a=x3ARPjZmWFM:i6I2_VNd5aI:YwkR-u9nhCs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CSharperImage?d=YwkR-u9nhCs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/CSharperImage?a=x3ARPjZmWFM:i6I2_VNd5aI:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CSharperImage?i=x3ARPjZmWFM:i6I2_VNd5aI:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/CSharperImage?a=x3ARPjZmWFM:i6I2_VNd5aI:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CSharperImage?i=x3ARPjZmWFM:i6I2_VNd5aI:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/CSharperImage?a=x3ARPjZmWFM:i6I2_VNd5aI:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CSharperImage?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/CSharperImage?a=x3ARPjZmWFM:i6I2_VNd5aI:I9og5sOYxJI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CSharperImage?d=I9og5sOYxJI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/CSharperImage/~4/x3ARPjZmWFM" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://csharperimage.jeremylikness.com/feeds/5108722851039396553/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://csharperimage.jeremylikness.com/2010/02/vancouver-olympics-howd-we-do-that.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8944256652433533647/posts/default/5108722851039396553?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8944256652433533647/posts/default/5108722851039396553?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/CSharperImage/~3/x3ARPjZmWFM/vancouver-olympics-howd-we-do-that.html" title="Vancouver Olympics - How'd We Do That?" /><author><name>Jeremy Likness</name><uri>http://www.blogger.com/profile/18407945801671553594</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="05667915713066003387" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://csharperimage.jeremylikness.com/2010/02/vancouver-olympics-howd-we-do-that.html</feedburner:origLink></entry><entry gd:etag="W/&quot;D0IGQ3g7eip7ImA9WxBUFk8.&quot;"><id>tag:blogger.com,1999:blog-8944256652433533647.post-1301455103702925696</id><published>2010-02-23T13:15:00.008-05:00</published><updated>2010-03-03T09:12:02.602-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-03-03T09:12:02.602-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="silverlight myths" /><title>Top 10 Silverlight Myths and the Facts to Bust Them</title><content type="html">&lt;p&gt;Silverlight is a client side plug-in based technology that has been in production since late 2007. I've been a web developer for well over a decade now, and recently have focused almost exclusively on Silverlight since version 3.0 was released. It astounds me how many people still resist Silverlight because they either don't understand what it is or haven't taken the time to research the capabilities it provides. Silverlight is a strong, mature technology that is being used on production sites to deliver powerful applications right here, right now. It's not emerging and it's not experimental. 
&lt;p&gt;From my experience answering questions about Silverlight on both Twitter and various forums and discussion groups, I've come up with ten common myths that I hear of over and over again. My hope is this one post can serve as a central place to address those myths, provide the facts that bust the myths, and help potential Silverlight users and developers better understand and take advantage of what I consider to be amazing technology. Feel free to share your thoughts in the comments at the end of this post and share this link with anyone who will gain value learning about the truth! 
&lt;p style="font-size: large;"&gt;&lt;b&gt;Myth:&lt;/b&gt; &lt;i&gt;"Silverlight is mainly for video."&lt;/i&gt;
&lt;p&gt;&lt;b&gt;Fact:&lt;/b&gt; Video is only the tip of the iceberg.
&lt;p&gt;Silverlight is a cross-browser, cross-platform, and cross-device plug-in used for creating rich applications on the Internet. In addition to a powerful video stack that makes it easy to deliver video using most of the widely available codecs, Silverlight also boasts a powerful client networking stack (making it easy to connect to third-party services like Facebook and Twitter, using SOAP, REST, or even raw TCP sockets). It has a robust data access model that uses a concept known as data-binding to render data. This makes it ideal for line of business applications due to the relative ease of taking business classes and exposing the data through a rich, interactive user experience. Silverlight also boasts a very robust layout and styling engine and comes with literally hundreds of controls and behaviors ready to be integrated into your applications.
&lt;p&gt;To see what's possible with Silverlight, take a look at the &lt;a href="http://silverlight.net/showcase/" target="_blank"&gt;Silverlight Showcase&lt;/a&gt;. For an example of how Silverlight provides an effective "line of business" experience, check out Microsoft's &lt;a href="http://www.mscui.net/PatientJourneyDemonstrator/" target="_blank"&gt;Health CUI Patient Journey Demonstrator&lt;/a&gt;. Here is another list of &lt;a href="http://ux.artu.tv/?page_id=147" target="_blank"&gt;25 inspiring Silverlight projects&lt;/a&gt;.
&lt;p style="font-size: large;"&gt;&lt;b&gt;Myth:&lt;/b&gt; &lt;i&gt;"Silverlight requires Microsoft web servers to run."&lt;/i&gt;
&lt;p&gt;&lt;b&gt;Fact:&lt;/b&gt; Silverlight applications can be served from any web server that supports configuring MIME types.
&lt;p&gt;Silverlight is packaged into a file called a XAP file. This file is actually a special zip file that contains the content necessary to run a Silverlight application. Because this content is completely self contained, there are only two steps required to successfully run the application: first, the server must provide the content to the end user via their browser, and second, the browser must load and run the content via the Silverlight plug-in. 
&lt;p&gt;Take a look at &lt;a href="http://silverlightphp.codeplex.com/" target="_blank"&gt;Embedding Silverlight in PHP&lt;/a&gt;. If you wish to host the Silverlight application on a server such as Apache, you simply need to store the XAP file on the server, and add the MIME type for the extension &lt;code&gt;.xap&lt;/code&gt; of &lt;code&gt;application/x-Silverlight-app&lt;/code&gt; and the user's browser will do the rest!
&lt;p style="font-size: large;"&gt;&lt;b&gt;Myth:&lt;/b&gt; &lt;i&gt;"Microsoft tools for Silverlight are expensive."&lt;/i&gt;
&lt;p&gt;&lt;b&gt;Fact:&lt;/b&gt; You can develop fully functional Silverlight applications at no cost.
&lt;p&gt;Actually, you can grab everything you need to develop Silverlight absolutely free. Take a look at the &lt;a href="http://silverlight.net/getstarted/" target="_blank"&gt;Silverlight Get Started&lt;/a&gt; page. There, you can download everything you need to build fully functional Silverlight applications. There is an SDK, toolkits, extensions, and even links to helpful tutorials to get started. While there are trial versions of additional tool sets such as Expression to help you get started, these are not required to build your applications.
&lt;p&gt;Are you more of an open source person and prefer a different IDE? Check out the &lt;a href="http://www.eclipse4sl.org/" target="_blank"&gt;Eclipse Tools for Silverlight&lt;/a&gt;, an open source IDE that allows Java developers to build Silverlight applications.
&lt;p&gt;Keep in mind the SDK works perfectly well with the Express (free) edition of the Visual Studio IDE that is &lt;a href="http://www.microsoft.com/express/Web/" target="_blank"&gt;available for download here&lt;/a&gt;. You can grab the 2008 edition for Silverlight 3 development and the upcoming 2010 for future Silverlight 4.
&lt;p style="font-size: large;"&gt;&lt;b&gt;Myth:&lt;/b&gt; &lt;i&gt;"Silverlight doesn't work on ... (Mac, Chrome, etc.)"&lt;/i&gt;
&lt;p&gt;&lt;b&gt;Fact:&lt;/b&gt; Silverlight is supported on all of the most popular browser and operating system combinations.
&lt;p&gt;This is a common myth. Silverlight support is broad and while there are some obscure combinations that are not supported yet, all of the major used browser and platform combinations are supported.
&lt;p&gt;According to the W3Schools &lt;a href="http://www.w3schools.com/browsers/browsers_stats.asp" target="_blank"&gt;Browser Statistics&lt;/a&gt;, the top three browsers are Internet Explorer (versions 6, 7, and 8) followed by Firefox, Chrome, and Safari. Opera trails at 2.2% of the market. 
&lt;p&gt;The top 5 browser operating systems are all Windows operating systems which account for 90% of browsers that visit the website. Mac commands 6.8% and Linux 4.6% as of January 2010. 
&lt;p&gt;Based on these statistics, Silverlight is supported on the major operating systems and browsers (FireFox, IE, and Safari). While there is not official Microsoft support for Chrome until Silverlight 4, most report it runs just fine in that browser as well. The plug-in is supported on Intel-based Macs for both Safari and Firefox. While there is currently no Linux support, the &lt;a href="http://en.wikipedia.org/wiki/Microsoft_Silverlight" target="_blank"&gt;Moonlight project&lt;/a&gt; is working toward that goal with &lt;a href="http://www.microsoft.com/interop/msnovellcollab/moonlight.mspx" target="_blank"&gt;Microsoft's full blessing&lt;/a&gt;. There is no PowerPC support for anything other than version 1.0, but the majority of Mac computers are Intel-based according to &lt;a href="http://en.wikipedia.org/wiki/File:Macsales.svg" target="_blank"&gt;this chart&lt;/a&gt;. 
&lt;p style="font-size: large;"&gt;&lt;b&gt;Myth:&lt;/b&gt; &lt;i&gt;"Silverlight is buggy."&lt;/i&gt;
&lt;p&gt;&lt;b&gt;Fact:&lt;/b&gt; Silverlight is in its third version production release and is used in many production websites without issue.
&lt;p&gt;This is one of those claims I believe comes from two sources: people who simply don't want to install or play with Silverlight, so they call websites "buggy" when they can't access them due to lack of the Silverlight plug-in, and people who don't understand the difference between a buggy framework or plug-in and bad code. 
&lt;p&gt;Like any other platform, Silverlight is simply a staging area for applications. It's up to the development community to write those applications. Some developers are certainly more skilled than others. So far I have yet to find a viable production "bug" related to the Silverlight runtime itself (as opposed to errors or bugs introduced by the developers). That doesn't mean they don't exist, but I haven't found it and I've written and supported a lot of code.
&lt;p&gt;If you're concerned about how stable Silverlight is, consider this: it is robust enough to power &lt;a href="http://team.silverlight.net/lighthouse-wins/sunday-night-football-powered-by-silverlight/" target="_blank"&gt;Sunday Night Football&lt;/a&gt;, the &lt;a href="http://techcrunch.com/2008/01/06/microsoft-silverlight-gets-a-high-profile-win-2008-bejing-olympics/" target="_blank"&gt;2008 Beijing Olympics&lt;/a&gt; (yes, that was two years ago) and the &lt;a href="http://team.silverlight.net/announcement/the-xxi-olympic-winter-games-on-nbcolympics-com-brought-to-you-in-full-hd-with-silverlight-and-smooth-streaming/" target="_blank"&gt;2010 Winter Olympics&lt;/a&gt;. Artist Alicia Keys used &lt;a href="http://team.silverlight.net/events/catch-alicia-keys-live-from-the-apollo-this-thursday-1-8-6pm-pst-powered-by-microsoft-silverlight/" target="_blank"&gt;Silverlight to stream her "Live from the Apollo" concert&lt;/a&gt;. 
&lt;p&gt;More importantly, there are a host of companies, including Fortune 500 companies, that use Silverlight every day to drive critical business operations. As an example, read about how my company, &lt;a href="http://www.wintellect.com/" target="_blank"&gt;Wintellect&lt;/a&gt;, worked with a &lt;a href="http://www.microsoft.com/casestudies/Case_Study_Detail.aspx?CaseStudyID=4000003684" target="_blank"&gt;financial solutions provider to build a web-based check deposit solution&lt;/a&gt; using Silverlight. Then &lt;a href="http://www.bing.com/search?q=silverlight+site%3Awww.microsoft.com%2Fcasestudies" target="_blank"&gt;click here to launch a Bing search&lt;/a&gt; that shows several more case studies for your review.
&lt;p style="font-size: large;"&gt;&lt;b&gt;Myth:&lt;/b&gt; &lt;i&gt;"HTML5 is going to kill Silverlight."&lt;/i&gt;
&lt;p&gt;&lt;b&gt;Fact:&lt;/b&gt; HTML5 and Silverlight are different technologies that provide solutions to different problems.
&lt;p&gt;This is a common topic of conversation on the web. Due mostly to the myth that Silverlight is only for video; the fact that many web browsers are adopting the new &lt;code&gt;&amp;lt;video&gt;&lt;/code&gt; tag, and major sites like YouTube are now supporting the standard, has led some to believe that both Flash and Silverlight are going away. 
&lt;p&gt;This couldn't be farther from the truth. According to several tracking sites like &lt;a href="http://riastats.com/#" target="_blank"&gt;RIAStats.com&lt;/a&gt;, the adoption rate of Silverlight is growing dramatically. Meanwhile, some browsers have adopted certain portions of the HTML5 standard and tout their support of "open standards" despite the fact that HTML5 &lt;i&gt;isn't actually a standard yet&lt;/i&gt;. Take a look at the &lt;a href="http://www.w3.org/html/wg/" target="_blank"&gt;W3C schedule&lt;/a&gt; for this. It won't even be an official recommendation until 2012, and isn't expected to be finalized until 2022. I'm not making this up, read the facts for yourself! 
&lt;p&gt;So as much as the dream is alive, any adoption now is not support for open standards, but premature support for draft standards that are subject to change. 
&lt;p&gt;Don't get me wrong, I'm not against HTML5. I think it is fantastic. But what HTML5 does is provide advanced markup for media. Silverlight, as you've read in this post, does much more than provide pretty graphics or stream video. For more on this topic, read &lt;a href="http://blog.iqinteractive.com/?p=338" target="_blank"&gt;Why HTML5 won't kill Flash or Silverlight&lt;/a&gt;.
&lt;p style="font-size: large;"&gt;&lt;b&gt;Myth:&lt;/b&gt; &lt;i&gt;"Silverlight is about smashing open standards."&lt;/i&gt;
&lt;p&gt;&lt;b&gt;Fact:&lt;/b&gt; Silverlight is a platform that functions in addition to, not against or contrary to, open standards.
&lt;p&gt;In a previous myth, I mentioned how slow the HTML5 ratification process is. However, there are browsers pushing support for features and I'm not saying that is a bad thing. In fact, Silverlight doesn't conflict with these standards. The latest version of Silverlight, version 4, that will soon be released has full support for HTML and rich content. This means it can host HTML code and even execute JavaScript and plug-ins within the application. It fully supports the open standards used to render web content.
&lt;p&gt;One of main arguments that Silverlight is "against open standards" is because of the video support. Opponents say that the HTML5 &lt;code&gt;&amp;lt;video&gt;&lt;/code&gt; tag is the way to go. While this sounds good in principle, there are a few issues with it. While the tag is adopted in several browsers, currently it is mainly good for simply playing, stopping, starting, and pausing videos. There is no built-in support for captioning (take a look at &lt;a href="http://dev.opera.com/articles/view/accessible-html5-video-with-javascripted-captions/" target="_blank"&gt;this article&lt;/a&gt; to see how difficult it is to even attempt captioning using HTML5). There is no support for adaptive streaming technologies (like &lt;a href="http://www.iis.net/expand/SmoothStreaming" target="_blank"&gt;IIS Smooth Streaming&lt;/a&gt;) which improve the user experience by degrading gracefully to lower bit rates when the network slows, rather than stopping the video and showing the annoying "buffering" icon and forcing the user to wait 15 seconds.
&lt;p&gt;Silverlight makes it easy to provide videos with rich content, including chapter navigation and support for captioning. Furthermore, with the full DOM support, it is also easy to fall back to other video rendering methods. In a recent project I worked on, I built a Silverlight control to play videos in a PHP page. I used JavaScript to detect if the user had the plug-in installed. If not, I'd simply launch the direct video instead so that it could still be played on browsers that don't support Silverlight.
&lt;p&gt;To further complicate the matter are dubious claims on the web about "open standards achievements" that, well, aren't really "open." Take a look at &lt;a href="http://weblog.bocoup.com/worlds-1st-html-audio-generated-music" target="_blank"&gt;the world's 1st HTML audio generated music&lt;/a&gt; (their claim, not mine.) It sounds great because it is entirely open standards, right? Then why are they showing it with a video clip instead of making it play in your browser? The kicker comes in the "try it yourself" section, where you find out you need a custom "audio write enabled version of the FireFox browser." That hardly sounds like an open standard to me. I don't need a custom browser to run my Silverlight applications that handle audio and video just fine!
&lt;p&gt;Again, I believe the main reason for this myth is really the perception that Silverlight is only good for playing videos and therefore is somehow competing with the HTML5 specification. Once you realize there is much, much more that can be done with Silverlight, you'll realize it is a way to get things done now, instead of having to resort to exotic JavaScript hacks or waiting for the open standards to catch up. 
&lt;p&gt;For another example of just how powerful the Silverlight experience can be, take a look at &lt;a href="http://www.bing.com/maps/explore/#" target="_blank"&gt;Bing Maps&lt;/a&gt; and zoom into the streets of Seattle, Washington. While zoomed in, click the little blue person to go to the street level view. These types of experiences just aren't possible with the current "open standards" and therefore provide an immediate solution until the standards can come to terms with technology advances.
&lt;p&gt;Are you still holding out on installing the plugin? You can view the &lt;a href="http://www.techflash.com/seattle/2010/02/video_bing_maps_at_ted.html" target="_blank"&gt;Bing Maps experience in a video&lt;/a&gt; posted at TED. This one, by the way, is streamed using the most popular "standard" for showing video today: the completely proprietary Flash plug-in that was produced not by an open standards committee, but a corporation called Adobe. (It's an interesting fact that the people who are extremely vocal about HTML5 being the video standard still watch most of their videos using Flash ... only recently have a few major websites such as YouTube actually adopted the "HTML5 standard.") 
&lt;p style="font-size: large;"&gt;&lt;b&gt;Myth:&lt;/b&gt; &lt;i&gt;"It's hard to develop for Silverlight."&lt;/i&gt;
&lt;p&gt;&lt;b&gt;Fact:&lt;/b&gt; Silverlight is based on the Common Language Runtime (CLR) and can therefore be written in multiple languages.
&lt;p&gt;There is no need to reinvent the wheel. .NET developers will find native C# and VB.Net support. While the XAML markup language comes with a learning curve, most people admit that it is a powerful tool and the time to master it well worth the experience it provides. Silverlight can be written using IronPython, and I've already mentioned the project to make it available to Java programmers. 
&lt;p&gt;The learning curve is no greater than most other languages and I would argue as a framework it is vastly superior for web programming. One of the reasons I began building Silverlight applications was because I could create richer real-time applications with better performance in a faster time frame using Silverlight over traditional HTML plus JQuery web pages. I didn't have to write exotic solutions to maintain state between page calls or support multiple browsers. Once you write the code, it runs wherever the plug-in is supported. The data-binding and XAML markup make it incredibly easy to develop very complex user interfaces in a short amount of time featuring full validation. 
&lt;p&gt;The IDE for Silverlight supports features such as drag-and-drop behaviors and tons of widgets and controls. In the next version to be released, there is even drag-and-drop data access support. I don't necessarily consider this a good thing: the argument that it is difficult to develop is typically because it's something new to learn. Unfortunately, many developers have been spoiled by easy "drag and drop" frameworks that might build websites quickly while sacrificing some scalability, useability, and performance. Most developers who are used to building solid architectures find that Silverlight helps, rather than hinders, their development efforts, while the developers who depend on crutches like completely auto-generated websites based on database models will struggle with learning best practices for multi-tiered applications.
&lt;p&gt;&lt;i&gt;Community Feedback Links (see comments):&lt;/i&gt;
&lt;ul&gt;&lt;li&gt;An application built in 6 hours with Silverlight: &lt;a href="http://www.youtube.com/watch?v=UoNr_xjGvic" target="_blank"&gt;http://www.youtube.com/watch?v=UoNr_xjGvic&lt;/a&gt;&lt;/ul&gt;
&lt;p style="font-size: large;"&gt;&lt;b&gt;Myth:&lt;/b&gt; &lt;i&gt;"There aren't good materials to learn Silverlight."&lt;/i&gt; 
&lt;p&gt;&lt;b&gt;Fact&lt;/b&gt;: The Silverlight community is teeming with individuals and websites designed to help you learn it as quickly and effectively as possible.
&lt;p&gt;One complaint I hear is that there aren't enough books out on Silverlight or various design patterns such as MVVM (model-view-view model) that are used in Silverlight. One of the issues is that the technology is moving at a very fast pace ... just a few years after launch, and we're moving to version 4.0 ... so the web is often the best way to get the latest information. 
&lt;p&gt;The main Silverlight site is &lt;a href="http://silverlight.net/learn/" target="_blank"&gt;loaded with tutorials&lt;/a&gt; to teach you how to write Silverlight, with topics ranging from basic to advanced. Then there are videos like &lt;a href="http://victorgaudioso.wordpress.com/" target="_blank"&gt;Victor Gaudioso's on-line tutorials&lt;/a&gt; and the consistently updated &lt;a href="http://channel9.msdn.com/shows/SilverlightTV/" target="_blank"&gt;Silverlight TV&lt;/a&gt;. The &lt;a href="http://www.silverlightcream.com/" target="_blank"&gt;Silverlight Cream&lt;/a&gt; website keeps you up to date with the latest articles, tutorials, and blog posts related to Silverlight. Pose a question to the &lt;A href="http://silverlight.net/forums/" target="_blank"&gt;Silverlight Forums&lt;/a&gt; and you are likely to receive a response within minutes. Take a look at all of the &lt;a href="http://www.bing.com/search?q=silverlight+users+group" target="_blank"&gt;Silverlight Users' Groups&lt;/a&gt;. 
&lt;p&gt;Need more advanced training? Our own company has in depth training available from Jeff Prosise's &lt;a href="https://www.wintellect.com/Registration/WintellectRegistration.aspx" target="_blank"&gt;Silverlight Party&lt;/a&gt; to &lt;a href="http://www.wintellect.com/CourseDetail.aspx?Course=45" target="_blank"&gt;Silverlight for Designers&lt;/a&gt; and our flagship &lt;a href="http://devscovery.com/" target="_blank"&gt;Devscovery Conference&lt;/a&gt; (we have a full day devoted to Silverlight in New York). 
&lt;p&gt;There is plenty of material out there if you are willing to read, watch, and attend.
&lt;p&gt;&lt;i&gt;Community Feedback Links (see comments):&lt;/i&gt;
&lt;ul&gt;&lt;li&gt;Sparkling Client (podcasts): &lt;a href="http://www.sparklingclient.com/" target="_blank"&gt;SparklingClient.com&lt;/a&gt;
&lt;li&gt;Sparkling Client (podcasts): &lt;a href="http://www.sparklingclient.com/prism-silverlight/" target="_blank"&gt;PRISM at SparklingClient.com&lt;/a&gt;
&lt;li&gt;Top 20 Resources to Get Started... &lt;a href="http://ux.artu.tv/?p=136" target="_blank"&gt;Microsoft UX Chit Chat&lt;/a&gt;&lt;/ul&gt;
&lt;p style="font-size: large;"&gt;&lt;b&gt;Myth:&lt;/b&gt; &lt;i&gt;"There aren't many practical Silverlight applications."&lt;/i&gt;
&lt;p&gt;&lt;b&gt;Fact:&lt;/b&gt; Silverlight is right here, right now, with satisfied customers using production applications to streamline business process, provide a media presence, offer gaming experiences, and more.
&lt;p&gt;This is by far the main myth that is shattered by the others. Going from assuming Silverlight is "just for videos" to this is an important step in understanding what Silverlight can do. I've already mentioned the Bing maps experience, pointed you to the showcase of applications and the sample application Microsoft provides for healthcare. There are sites devoted to &lt;a href="http://www.mashooo.com/SilverlightGames.aspx" target="_blank"&gt;Silverlight games&lt;/a&gt;. You can &lt;a href="http://89.206.186.140/ttp_eh/silverlight/ttp.html" target="_blank"&gt;view Darwin's field notes on-line&lt;/a&gt; and &lt;a href="http://memorabilia.hardrock.com/" target="_blank"&gt;browse hardrock memorabilia&lt;/a&gt;. This is all in addition to the various line of business applications that are on intranets monitoring the health of servers, providing interactive interfaces to upload, transport, and archive data, and real time visual feedback for statistics businesses care about.
&lt;p&gt;If I've appeared somewhat biased in my discourse on Silverlight, it's because I am. I've written PHP, AJAX, wired interactive sites with JQuery and used XML and XSLT as "open standards" to drive content-based websites. In all of my years working on the web, I've found Silverlight to be one of the most compelling platforms for creating truly amazing experiences both on-line and, with support from the newer releases, offline as well. 
&lt;p&gt;Having said that, I also don't believe Silverlight is the only programming platform. There are many cases where other tools and languages are required, whether it is because of the platform (i.e. a mobile device or desktop application), the content (for example, I wouldn't write a mostly text-based content management system in Silverlight), or the target audience. However, it's important that people understand what is possible so they don't get lost in pointless and irrational rants against technologies they haven't taken the time to understand.
&lt;p&gt;Please share you thoughts and feedback below!
&lt;p&gt;&lt;a href="http://jeremylikness.com/" title="Jeremy Likness"&gt;&lt;img border="0" src="http://jeremylikness.com/signature.gif" alt="Jeremy Likness" title="Jeremy Likness"/&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8944256652433533647-1301455103702925696?l=csharperimage.jeremylikness.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/CSharperImage?a=GdgMalH0lZA:gUYIb9lvYOA:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CSharperImage?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/CSharperImage?a=GdgMalH0lZA:gUYIb9lvYOA:YwkR-u9nhCs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CSharperImage?d=YwkR-u9nhCs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/CSharperImage?a=GdgMalH0lZA:gUYIb9lvYOA:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CSharperImage?i=GdgMalH0lZA:gUYIb9lvYOA:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/CSharperImage?a=GdgMalH0lZA:gUYIb9lvYOA:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CSharperImage?i=GdgMalH0lZA:gUYIb9lvYOA:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/CSharperImage?a=GdgMalH0lZA:gUYIb9lvYOA:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CSharperImage?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/CSharperImage?a=GdgMalH0lZA:gUYIb9lvYOA:I9og5sOYxJI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CSharperImage?d=I9og5sOYxJI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/CSharperImage/~4/GdgMalH0lZA" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://csharperimage.jeremylikness.com/feeds/1301455103702925696/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://csharperimage.jeremylikness.com/2010/02/top-10-silverlight-myths-and-facts-to.html#comment-form" title="11 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8944256652433533647/posts/default/1301455103702925696?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8944256652433533647/posts/default/1301455103702925696?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/CSharperImage/~3/GdgMalH0lZA/top-10-silverlight-myths-and-facts-to.html" title="Top 10 Silverlight Myths and the Facts to Bust Them" /><author><name>Jeremy Likness</name><uri>http://www.blogger.com/profile/18407945801671553594</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="05667915713066003387" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">11</thr:total><feedburner:origLink>http://csharperimage.jeremylikness.com/2010/02/top-10-silverlight-myths-and-facts-to.html</feedburner:origLink></entry><entry gd:etag="W/&quot;AkQBSXY7fSp7ImA9WxBVFUk.&quot;"><id>tag:blogger.com,1999:blog-8944256652433533647.post-200456131208509534</id><published>2010-02-18T21:50:00.000-05:00</published><updated>2010-02-18T21:59:18.805-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-02-18T21:59:18.805-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="silverlight" /><category scheme="http://www.blogger.com/atom/ns#" term="ndepend" /><title>A Fluent RSS Reader for Silverlight Part 2: NDepends on What you Need</title><content type="html">&lt;p&gt;&lt;a href="http://ndepend.com/" target="_blank"&gt;NDepend&lt;/a&gt; is a product that analyzes large code bases and provides information about dependencies, complexity of code, best practices, and more. While designed to help manage large code bases, it also works well as a "reality check" as you are developing new projects. The latest release supports Silverlight and I'll be using it to clean up my RSS reader a little bit.
&lt;p&gt;The first thing I did was download and install the product. There is an option to integrate with Visual Studio. I chose this option, then opened the RSS reader solution. In the lower right I now have an option to create a new NDepend project and link it to my solution:
&lt;p&gt;&lt;img src="http://gallery.jeremylikness.com/main.php?g2_view=core.DownloadItem&amp;g2_itemId=195&amp;g2_serialNumber=1" title="NDepend add new project"/&gt;
&lt;p&gt;A new dialog pops up that prompts me for the projects/assemblies to scan and some other information. In this case, I simply take all of the defaults and click OK.
&lt;p&gt;&lt;img src="http://gallery.jeremylikness.com/main.php?g2_view=core.DownloadItem&amp;g2_itemId=198&amp;g2_serialNumber=2" title="NDepend project dialog"/&gt;
&lt;p&gt;This creates the new project and analyzes my project immediately. Eventually, I'm brought to a new web page that has a detailed report of the analysis of my solution.
&lt;p&gt;The report is very comprehensive. For example, I receive summary statistics at the top:
&lt;pre&gt;
Number of IL instructions: 1003
Number of lines of code: 120
Number of lines of comment: 265
Percentage comment: 68
Number of assemblies: 3
Number of classes: 15
Number of types: 16
Number of abstract classes: 0
Number of interfaces: 1
Number of value types: 0
Number of exception classes: 0
Number of attribute classes: 1
Number of delegate classes: 0
Number of enumerations classes: 0
Number of generic type definitions: 1
Number of generic method definitions: 6
Percentage of public types: 81.25% 
Percentage of public methods: 76.81% 
Percentage of classes with at least one public field: 6.25% 
&lt;/pre&gt;
&lt;p&gt;The visual map gives me a quick idea of what the dependencies of the project are (click for a larger view):
&lt;p&gt;&lt;a href="http://gallery.jeremylikness.com/main.php?g2_itemId=200&amp;g2_imageViewsIndex=1" target="_blank" title="Visual NDepend"&gt;&lt;img src="http://gallery.jeremylikness.com/main.php?g2_view=core.DownloadItem&amp;g2_itemId=201&amp;g2_serialNumber=2" border="0" title="Visual NDepend" alt="Visual NDepend"/&gt;&lt;/a&gt;
&lt;p&gt;I also get a nice chart showing the dependencies ... you can imagine how powerful this visualization becomes when you have far more projects than the ones in our little RSS reader:
&lt;p&gt;&lt;img src="http://gallery.jeremylikness.com/main.php?g2_view=core.DownloadItem&amp;g2_itemId=204&amp;g2_serialNumber=2" title="NDepend Component Dependencies"/&gt;
&lt;p&gt;OK, that's all good and pretty, but how does this help us? We need to dive deeper into the report. Scrolling down the report, the first thing that happens is I am scolded for not commenting my &lt;code&gt;SecurityToken&lt;/code&gt; method well enough. There is a lot of code but I'm not explaining what the code is doing ... that's fine. It'll certainly help other developers down the road, but what about performance and code quality?
&lt;p&gt;The report indicates that my &lt;code&gt;Item&lt;/code&gt;, &lt;code&gt;RSSElementAttribute&lt;/code&gt;, and &lt;code&gt;Channel&lt;/code&gt; classes are candidates to be &lt;i&gt;sealed&lt;/i&gt;. Why would I want to seal the classes? Many C# developers mistakenly believe that you only seal a class when you want to prevent someone else from deriving from it. Not true.
&lt;p&gt;As Wintellect's own Jeffrey Richter explains in &lt;a href="http://www.wintellect.com/CS/blogs/jeffreyr/archive/2009/11/01/what-s-new-in-clr-via-c-3rd-edition-as-compared-to-the-2nd-edition.aspx" target="_blank"&gt;CLR via C#&lt;/a&gt;, there are three key reasons why a sealed class is better than an unsealed one:
&lt;ol&gt;&lt;li&gt;&lt;b&gt;Versioning&lt;/b&gt; &amp;mdash; if you need to unseal it in the future, you can do so without breaking compatibility&lt;li&gt;&lt;b&gt;Performance&lt;/b&gt; &amp;mdash; because  the class is sealed, the compiler can generate non-virtual calls (which have less overhead) rather than virtual calls (virtual calls are required to analyze the inheritance chain and find the correct instance of the actual method to call)&lt;li&gt;&lt;b&gt;Security and Predictability&lt;/b&gt; &amp;mdash; classes should manage and protect their state. Allowing a class to be derived exposes that class to corruption via the deriving code.&lt;/ol&gt;
&lt;p&gt;Turns out NDepend has given us a pretty good pointer there. We'll come back to these classes in a bit.
&lt;p&gt;Next, I find out two of my classes, &lt;code&gt;Channel&lt;/code&gt; and &lt;code&gt;RssReader&lt;/code&gt;, are candidates for structures. Structures have certain performance benefits (read more about them &lt;a href="http://msdn.microsoft.com/en-us/library/aa288471(VS.71).aspx" target="_blank"&gt;here&lt;/a&gt;) but if they are too large they may actually degrade performance. A class that is relatively small, has no derived types, and derives directly from &lt;code&gt;System.Object&lt;/code&gt; is a candidate for a structure. For the &lt;code&gt;Channel&lt;/code&gt; class, we can kill two birds with one stone: structures are also implicitly sealed.
&lt;p&gt;I could go on and on ... my next step is to continue finding areas that the Code Query Language constraints are fired and see if it makes sense to correct them. You can read more about the CQL &lt;a href="http://ndepend.com/CQL.htm" target="_blank"&gt;here&lt;/a&gt;. This language allows you to write your own constraints for quality checking your code. Let's jump out of the constraints and look at a few more metrics that the report provides.
&lt;p&gt;Fortunately, most of the items on the report contain hyperlinks to explanations of what the metric or query is. The list of basic metrics is explained &lt;a href="http://ndepend.com/Metrics.aspx" target="_blank"&gt;here&lt;/a&gt;. These are important ones to look into:
&lt;p&gt;&lt;b&gt;Afferent Coupling&lt;/b&gt; &amp;mdash; this is how many types outside of an assembly depend on the current type. A high afferent coupling means the type has a larger responsibility because more external types depend on it. In our case, only the common project generates this type of dependency.
&lt;p&gt;&lt;b&gt;Efferent Coupling&lt;/b&gt; &amp;mdash; this is simply how many external types to the current assembly are depended upon by types within the assembly. A high efferent coupling means we have many dependencies on other types. There will always be efferent coupling, because in the basic sense your string, int, and other framework types have a dependency on the core library. 
&lt;p&gt;Poor design results in efferent coupling increasing as you move from the database to the presentation layer. This is because more dependencies on database, business, and other types accumulate. A quality design will ensure consistency across the layers, because the presentation layer will only couple to models and types defined in the business layer, but will be completely abstracted from the data layer, etc.
&lt;p&gt;&lt;b&gt;Relational Cohesion&lt;/b&gt; &amp;mdash; this refers to interdependencies within an assembly. Typically, related types should be grouped together. A low relational cohesion means there are very few interdependencies. This is not always bad. For example, if you have your domain models in a single assembly, the relational cohesion will depend on how many of those classes aggregate or compose other classes ... it is perfectly normal to have several unrelated types defined. On the flip side, a high cohesion means perhaps the classes are too interrelated and should be broken out for better de-coupling. There is no hard, set rule for this and really is a judgment call based on the specific project being analyzed.
&lt;p&gt;&lt;b&gt;Instability&lt;/b&gt; is an important metric to consider. It is the ratio of efferent coupling to total coupling. On a scale from 0 to 1, this describes the "resistance to change" for the assembly. A 0 means it is highly resistant to change, while a 1 means it is extremely instable, or highly sensitive to changes. Because I have grouped models, services, and interfaces together in my project, it fails with a score of 1. This means I need to re-factor and break some elements out so they are more independent. 
&lt;p&gt;&lt;b&gt;Abstractness&lt;/b&gt; is another important measure. This measures the ratio of abstract (interfaces and abstract classes) types to concrete types. It is again on a scale from 0 to 1. I try to target a combination of 0 and 1 for this metric ... the "1" or completely abstract being independent projects that define interfaces, with the "0" being the implementations of those interfaces. We'll re-factor the RSS reader to pull the interfaces and abstract classes to separate projects and then re-analyze. This will also help me with my testing efforts because it's very hard to write quality unit tests for highly coupled classes.
&lt;p&gt;Based on the report, I need to do some refactoring and change the types and modifiers of some of my entities, as well as split these out into separate projects.
&lt;p&gt;Doing this from within the project is simple. You can click on the NDepend icon and get a summary (click for full-sized view):
&lt;p&gt;&lt;a href="http://gallery.jeremylikness.com/main.php?g2_itemId=209&amp;g2_imageViewsIndex=1" target="_blank"&gt;&lt;img src="http://gallery.jeremylikness.com/main.php?g2_view=core.DownloadItem&amp;g2_itemId=210&amp;g2_serialNumber=2" border="0"/&gt;&lt;/a&gt;
&lt;p&gt;Next, I click on one of the warning rows to view the detail (for example unused code -&gt; potentially dead methods). This gives me the detail of the violation and where potential violations occurred. I can easily click on the member or class to navigate to the code and fix it directly:
&lt;p&gt;&lt;img src="http://gallery.jeremylikness.com/main.php?g2_view=core.DownloadItem&amp;g2_itemId=212&amp;g2_serialNumber=1" alt="NDepend Navigation" title="NDepend Navigation"/&gt;
&lt;p&gt;Following the advice of the tool, I created a new "model" project where I moved the basic domain entities (item, channel) and the custom attribute. I followed the advice to seal the classes but left them as classes due to the reflection used to generate instances from the RSS feeds. 
&lt;p&gt;A new service project was created to implement the service. Note how important this is because now for unit tests of classes that depend on the service contract, I can simply mock the interface rather than having to pull in an assembly with an actual implementation (read about &lt;a href="http://csharperimage.jeremylikness.com/2010/02/using-moq-with-silverlight-for-advanced.html" target="_blank"&gt;Using Moq for Silverlight for Advanced Unit Tests&lt;/a&gt;). 
&lt;p&gt;I also flattened my structure a bit. I had namespaces with only one class simply because I was dumping these into folders, rather than simply grouping them together and refactoring down the road when it makes sense.
&lt;p&gt;After all of this, I ended up with the new dependency diagram:
&lt;p&gt;&lt;img src="http://gallery.jeremylikness.com/main.php?g2_view=core.DownloadItem&amp;g2_itemId=207&amp;g2_serialNumber=2" title="Refactored NDepend Diagram"/&gt;
&lt;p&gt;My new assemblies no longer have instability ratings of "1" which means the solution as a whole is moving toward better stability and long term maintainability.
&lt;p&gt;Obviously this was a small project with few changes. The power of the tool increases exponentially as you build more complex and involved projects. It can help you sort dependencies, optimize your code, enforce naming conventions, and much more. 
&lt;p&gt;Now we've got the reader a little better suited for future expansion. My next step will be to build the unit tests (that should have gotten there a lot sooner, I know, I know) and then see if it makes sense to introduce any type of dependency injection.
&lt;p&gt;&lt;a href="http://jeremylikness.com/" title="Jeremy Likness"&gt;&lt;img border="0" src="http://jeremylikness.com/signature.gif" alt="Jeremy Likness" title="Jeremy Likness"/&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8944256652433533647-200456131208509534?l=csharperimage.jeremylikness.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/CSharperImage?a=Tu2Fj-oHHCY:RAryGiem-r8:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CSharperImage?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/CSharperImage?a=Tu2Fj-oHHCY:RAryGiem-r8:YwkR-u9nhCs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CSharperImage?d=YwkR-u9nhCs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/CSharperImage?a=Tu2Fj-oHHCY:RAryGiem-r8:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CSharperImage?i=Tu2Fj-oHHCY:RAryGiem-r8:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/CSharperImage?a=Tu2Fj-oHHCY:RAryGiem-r8:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CSharperImage?i=Tu2Fj-oHHCY:RAryGiem-r8:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/CSharperImage?a=Tu2Fj-oHHCY:RAryGiem-r8:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CSharperImage?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/CSharperImage?a=Tu2Fj-oHHCY:RAryGiem-r8:I9og5sOYxJI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CSharperImage?d=I9og5sOYxJI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/CSharperImage/~4/Tu2Fj-oHHCY" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://csharperimage.jeremylikness.com/feeds/200456131208509534/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://csharperimage.jeremylikness.com/2010/02/fluent-rss-reader-for-silverlight-part_18.html#comment-form" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8944256652433533647/posts/default/200456131208509534?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8944256652433533647/posts/default/200456131208509534?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/CSharperImage/~3/Tu2Fj-oHHCY/fluent-rss-reader-for-silverlight-part_18.html" title="A Fluent RSS Reader for Silverlight Part 2: NDepends on What you Need" /><author><name>Jeremy Likness</name><uri>http://www.blogger.com/profile/18407945801671553594</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="05667915713066003387" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">1</thr:total><feedburner:origLink>http://csharperimage.jeremylikness.com/2010/02/fluent-rss-reader-for-silverlight-part_18.html</feedburner:origLink></entry><entry gd:etag="W/&quot;AkIAR3k8eCp7ImA9WxBVEkk.&quot;"><id>tag:blogger.com,1999:blog-8944256652433533647.post-434431304021770561</id><published>2010-02-15T10:26:00.008-05:00</published><updated>2010-02-15T10:42:26.770-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-02-15T10:42:26.770-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="windows mobile 7" /><category scheme="http://www.blogger.com/atom/ns#" term="xbox live" /><category scheme="http://www.blogger.com/atom/ns#" term="zune" /><category scheme="http://www.blogger.com/atom/ns#" term="windows phone 7 series" /><title>Windows Phone 7 Series (Formerly called Windows Mobile 7)</title><content type="html">&lt;p&gt;There has been a lot of buzz around Microsoft's latest mobile phone operating system. I hope to be involved with this product as much as possible and will blog the detals that I can as they are made available. While the buzz has referred to this as "Windows Mobile 7" the platform has been officially renamed to "Windows Phone" and the next release is named, "7 Series." 
&lt;p&gt;Highlights of the announcement include a completely revamped user interface with Zune and XBox Live integration.
&lt;p&gt;To get an overview of what the phone looks like, see demos, and catch updates, visit the official website at &lt;a href="http://windowsphone7series.com/" target="_blank" title="Windows Phone 7 Series"/&gt;http://windowsphone7series.com/&lt;/a&gt;. 
&lt;p&gt;According to Steve Ballmer during the press release at the Mobile World Congress 2010, the phone will be available to purchase by Christmas 2010. 
&lt;p&gt;Here some Twitter feeds of individuals related to the project and tags to follow for official updates:
&lt;ul&gt;&lt;li&gt;&lt;a href="http://twitter.com/windowsphone" target="_blank"&gt;@windowsphone&lt;/a&gt;&lt;li&gt;&lt;a href="http://twitter.com/ckindel" target="_blank"&gt;@ckindel&lt;/a&gt;&lt;li&gt;&lt;a href="http://twitter.com/#search?q=%23wp7" target="_blank"&gt;#wp7&lt;/a&gt; &amp;mdash; Twitter search&lt;/ul&gt;
&lt;p&gt;Take a look at the Channel 9 first look "hands on demo": &lt;a href="http://channel9.msdn.com/posts/LauraFoy/First-Look-Windows-Phone-7-Series-Hands-on-Demo/" title="Windows Phone 7 Series Hands on Demo" target="_blank"&gt;First Look Windows Phone 7 Series Hands on Demo&lt;/a&gt;.
&lt;p&gt;The development platform and related toolsets will be announced at &lt;A href="http://live.visitmix.com/" target="_blank"&gt;MIX 2010&lt;/a&gt;. Take a look at this exclusive offer to learn how to build applications for the new platform for attendees: &lt;a href="http://live.visitmix.com/News/Exclusive-Windows-Phone-7-Series-Offer-for-MIX10-Attendees-WP7" target="_blank"&gt;Windows Phone 7 Series Offer for MIX10 Attendees&lt;/a&gt;. 
&lt;p&gt;That's all I've got, everything that is known right now can be found on these various sites. As I mentioned, I hope to be involved with this platform as much as possible over the next few months and will blog updates as they become generally available to the public. 
&lt;p&gt;Enjoy!
&lt;p&gt;&lt;a href="http://jeremylikness.com/" title="Jeremy Likness"&gt;&lt;img border="0" src="http://jeremylikness.com/signature.gif" alt="Jeremy Likness" title="Jeremy Likness"/&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8944256652433533647-434431304021770561?l=csharperimage.jeremylikness.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/CSharperImage?a=E_eDPLHIuRg:wyAK7xpewnI:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CSharperImage?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/CSharperImage?a=E_eDPLHIuRg:wyAK7xpewnI:YwkR-u9nhCs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CSharperImage?d=YwkR-u9nhCs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/CSharperImage?a=E_eDPLHIuRg:wyAK7xpewnI:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CSharperImage?i=E_eDPLHIuRg:wyAK7xpewnI:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/CSharperImage?a=E_eDPLHIuRg:wyAK7xpewnI:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CSharperImage?i=E_eDPLHIuRg:wyAK7xpewnI:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/CSharperImage?a=E_eDPLHIuRg:wyAK7xpewnI:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CSharperImage?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/CSharperImage?a=E_eDPLHIuRg:wyAK7xpewnI:I9og5sOYxJI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CSharperImage?d=I9og5sOYxJI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/CSharperImage/~4/E_eDPLHIuRg" height="1" width="1"/&gt;</content><link rel="related" href="http://windowsphone7series.com/" title="Windows Phone 7 Series (Formerly called Windows Mobile 7)" /><link rel="replies" type="application/atom+xml" href="http://csharperimage.jeremylikness.com/feeds/434431304021770561/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://csharperimage.jeremylikness.com/2010/02/windows-phone-7-series-formerly-called.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8944256652433533647/posts/default/434431304021770561?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8944256652433533647/posts/default/434431304021770561?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/CSharperImage/~3/E_eDPLHIuRg/windows-phone-7-series-formerly-called.html" title="Windows Phone 7 Series (Formerly called Windows Mobile 7)" /><author><name>Jeremy Likness</name><uri>http://www.blogger.com/profile/18407945801671553594</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="05667915713066003387" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://csharperimage.jeremylikness.com/2010/02/windows-phone-7-series-formerly-called.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DEcGRHY-eSp7ImA9WxBWFUo.&quot;"><id>tag:blogger.com,1999:blog-8944256652433533647.post-3521709576639163969</id><published>2010-02-07T15:50:00.002-05:00</published><updated>2010-02-07T15:53:45.851-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-02-07T15:53:45.851-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="rest services" /><category scheme="http://www.blogger.com/atom/ns#" term="silverlight" /><category scheme="http://www.blogger.com/atom/ns#" term="rss reader" /><category scheme="http://www.blogger.com/atom/ns#" term="cross domain" /><category scheme="http://www.blogger.com/atom/ns#" term="fluent interfaces" /><category scheme="http://www.blogger.com/atom/ns#" term="handler" /><title>A Fluent RSS Reader for Silverlight Part 1: Proof of Concept</title><content type="html">&lt;p&gt;One of the most common examples to help learn a language or framework is an RSS Reader. This is an ideal mini-project because it includes networking, parsing XML, and binding to data elements such as lists. I wanted to provide an example that shows some more interesting solutions that are possible using C# in Silverlight. This is the first part in a series. By the end of this post, we'll have a working reader. What I'll then do is add some more detailed error handling, provide unit tests, tackle skinning and visual states, and hopefully end up with a fairly advanced client. 
&lt;p&gt;Today, let's focus on getting a client where we can enter a feed and get some listings. A perfect way to test this will be a Twitter feed. If you would like to read my recent tweets as RSS, for example, you can simply navigate to &lt;a href="http://twitter.com/statuses/user_timeline/46210370.rss" target="_blank"&gt;http://twitter.com/statuses/user_timeline/46210370.rss&lt;/a&gt;. By viewing the source, you can see the basic structure of an RSS feed. It is fairly straightforward. 
&lt;p&gt;&lt;a href="http://www.wintellect.com/CS/files/folders/sample_files/entry12050.aspx" target="_blank"&gt;Download the source for this project&lt;/a&gt;
&lt;p&gt;&lt;b&gt;Domain Entities&lt;/b&gt;
&lt;p&gt;The first step is to define some domain entities. These are the "models" for our application, and represent the actual data we are working with. With an RSS feed, it is fairly simple. We'll work our way backward from the item up to the channel. Our item to start with looks like this: 
&lt;pre class="brush: csharp;"&gt; 
public class Item
{
    public string Title { get; set; }

    public string Description { get; set; }

    public DateTime PublishDate { get; set; }

    public string Guid { get; set; }

    public Uri Link { get; set; }
}
&lt;/pre&gt;
&lt;p&gt;A channel is simply some header information with a collection of items. For starters, we'll make it look like this: 
&lt;pre class="brush: csharp;"&gt;
public class Channel
{
    public Channel()
    {
        Items = new ObservableCollection&amp;lt;Item&gt;();
    }

    public string Title { get; set; }

    public Uri Link { get; set; }

    public string Description { get; set; }

    public ObservableCollection&amp;lt;Item&gt; Items { get; set; }
}
&lt;/pre&gt;
&lt;p&gt;Note that I build my entities based on the actual content, not how the content is delivered. In other words, even though the RSS stream may encode a link or a date as text, I want my domain entity to be able to work with the property as it was intended. Therefore, there are no "hacks" to force something into a Uri that doesn't belong: we use that type for the links. Similarly, the date time is handled as a date, and we can worry about how to display it when the time is right. The point is this keeps the data we're dealing with abstracted from the way we receive it, so if down the road we are reading a database or connecting to a different type of service, we only need to change the way we adapt from the service into our domain.
&lt;p&gt;&lt;b&gt;De-serialization&lt;/b&gt;
&lt;p&gt;One of the challenges we'll face with RSS feeds is taking the feed data and turning it into our domain objects (de-serializing the data). There are a number of different approaches, but I wanted to present one that I think makes it extremely easy to expand and extend entities that are mapped to XML documents. It involves using Silverlight's powerful LINQ to XML features.
&lt;p&gt;The concept is relatively simple: XML data is mostly strings in elements and attributes. For RSS feeds, the data is entirely in elements. Therefore, it should be relatively straightforward to parse an XML element into an entity. We'll know the target property and the type of that property, so all we need is the element and the conversion. 
&lt;p&gt;To tackle the element, I decided to create a custom attribute called &lt;code&gt;RssElement&lt;/code&gt; that allows me to tag a property with the name of the element the property's value is contained within. Here is the attribute:
&lt;pre class="brush: csharp;"&gt;
[AttributeUsage(AttributeTargets.Property,AllowMultiple = false)]
public class RssElementAttribute : System.Attribute
{
    public readonly string ElementName; 

    public RssElementAttribute(string elementName)
    {
        ElementName = elementName;
    }
}
&lt;/pre&gt;
&lt;p&gt;Now I can circle back to my entities and tag them with the source elements. First, the item:
&lt;pre class="brush: csharp;"&gt;
public class Item
{
    [RssElement("title")]
    public string Title { get; set; }

    [RssElement("description")]
    public string Description { get; set; }

    [RssElement("pubDate")]
    public DateTime PublishDate { get; set; }

    [RssElement("guid")]
    public string Guid { get; set; }

    [RssElement("link")]
    public Uri Link { get; set; }
}

&lt;/pre&gt;
&lt;p&gt;And then the channel:
&lt;pre class="brush: csharp;"&gt;
public class Channel
{
    public Channel()
    {
        Items = new ObservableCollection&lt;Item&gt;();
    }

    [RssElement("title")]
    public string Title { get; set; }

    [RssElement("link")]
    public Uri Link { get; set; }

    [RssElement("description")]
    public string Description { get; set; }

    public ObservableCollection&amp;lt;Item&gt; Items { get; set; }
}
&lt;/pre&gt;
&lt;p&gt;Now that we have a way of tagging the properties, we can create a fluent extension to move from an &lt;code&gt;XElement&lt;/code&gt; (what LINQ gives us) to an actual type.
&lt;p&gt;I created a static class called &lt;code&gt;LinqExtensions&lt;/code&gt; to extend my LINQ classes. Again, working backward, let's consider what happens to the value of an element in XML when we move it to our entity. We'll need to take that value (which is a string) and convert it based on the target type. It has a consistent method signature: receive a string, return a type. Therefore, I decided to implement a dictionary to map the conversion process to the target types. Working with the types I know I'll need, my dictionary looks like this: 
&lt;pre class="brush: csharp;"&gt;
public static class LinqExtensions
{
    private static readonly Dictionary&amp;lt;Type, Func&amp;lt;string, object&gt;&gt; _propertyMap;

    static LinqExtensions()
    {
        _propertyMap = new Dictionary&amp;lt;Type, Func&amp;lt;string, object&gt;&gt;
                           {
                               {typeof (string), s =&gt; s},
                               {typeof (Uri), s =&gt; new Uri(s)},
                               {typeof (DateTime), s =&gt; DateTime.Parse(s)}
                           };
    }
&lt;/pre&gt;
&lt;p&gt;This is very simple when you see where I'm going. Everything is mapped to a function that takes a string and returns an object. A string is a pass-through (&lt;code&gt;s =&gt; s&lt;/code&gt;). A Uri converts the string to a Uri (&lt;code&gt;s =&gt; new Uri(s)&lt;/code&gt;) and a date time attempts to parse the date (&lt;code&gt;s =&gt; DateTime.Parse(s)&lt;/code&gt;). By using the type as the key to the dictionary, I can do this:
&lt;pre class="brush: csharp;"&gt;
...
DateTime date = _propertyMap[typeof(DateTime)]("1/1/2010") as DateTime; 
...
&lt;/pre&gt;
&lt;p&gt;Of course, part of what we can do down the road is add some better error handling and contract checking. Next, let's use this conversion. I am taking in an element, then using the property information that I have to set the value onto an instance of the target class. Given a class instance &lt;code&gt;T&lt;/code&gt;, an element, and the information about a property, I can inspect the custom attribute to find the element name, then use the conversion for the type of the property to set the value. My method looks like this:
&lt;pre class="brush: csharp;"&gt;
private static void _ProcessProperty&amp;lt;T&gt;(T instance, PropertyInfo property, XContainer element)
{
    var attribute =
        (RssElementAttribute) (property.GetCustomAttributes(true)
                                  .Where(a =&gt; a is RssElementAttribute))
                                  .SingleOrDefault();

    XElement targetElement = element.Element(attribute.ElementName);

    if (targetElement != null &amp;&amp; _propertyMap.ContainsKey(property.PropertyType))
    {
        property.SetValue(instance, _propertyMap[property.PropertyType](targetElement.Value), null);
    }
}
&lt;/pre&gt;
&lt;p&gt;As you can see, we grab the element, find the value in the XML fragment we're passed, then use the property's &lt;code&gt;SetValue&lt;/code&gt; method to set the value based on the conversion we find in the property map. 
&lt;p&gt;How do we get the property info? Take a look at this fluent extension. It takes an element and is typed to a target class. It will create a new instance of the class and iterate the properties to set the values. By using it as a fluent extension, I can write this in code, which I think makes it very readable: 
&lt;pre class="brush: csharp;"&gt;
...
var widget = xmlElement.ParseAs&amp;lt;Widget&gt;(); 
...
&lt;/pre&gt;
&lt;p&gt;The "parse as" method looks like this:
&lt;pre class="brush: csharp;"&gt;
public static T ParseAs&amp;lt;T&gt;(this XElement element) where T : new()
{
    var retVal = new T();

    ((from p in typeof (T).GetProperties()
      where (from a in p.GetCustomAttributes(true) where a is RssElementAttribute select a).Count() &gt; 0
      select p).AsEnumerable()).ForEach(p =&gt; _ProcessProperty(retVal, p, element));

    return retVal;
}
&lt;/pre&gt;
&lt;p&gt;I basically grab all properties with the custom attribute, then pass the class, element, and property to the method we developed earlier to set the value. Finally, I return the new instance of the class. The &lt;code&gt;ForEach&lt;/code&gt; is available with the toolkit, but you can roll your own enumerator extension like this:
&lt;pre class="brush: csharp;"&gt;
public static class IteratorExtensions
{
    public static void ForEach&amp;lt;T&gt;(this IEnumerable&amp;lt;T&gt; list, Action&amp;lt;T&gt; action)
    {
        foreach(var item in list)
        {
            action(item);
        }
    }
}
&lt;/pre&gt;
&lt;p&gt;To me, it saves code and makes it easier to read what's going on if you have to perform a simple action and use the &lt;code&gt;ForEach&lt;/code&gt; extension to do it.
&lt;p&gt;While we're having fun with our fluent extensions, we're almost ready to take an RSS feed and turn it into a group of objects. We need a way to get the text we receive from the call into an XDocument, so I made this extension: 
&lt;pre class="brush: csharp;"&gt;
public static XDocument AsXDocument(this string xml)
{
    return XDocument.Parse(xml);
}
&lt;/pre&gt;
&lt;p&gt;We also need to take the XDocument and iterate the elements to build channels and items. Because we already built our &lt;code&gt;ParseAs&lt;/code&gt; method and have tagged the entities for channels and elements, this becomes as simple as: 
&lt;pre class="brush: csharp;"&gt;
public static List&amp;lt;Channel&gt; AsRssChannelList(this XDocument rssDoc)
{
    var retVal = new List&amp;lt;Channel&gt;();

    if (rssDoc.Root != null)
    {
        foreach(var c in rssDoc.Root.Elements("channel"))
        {
            var channel = c.ParseAs&amp;lt;Channel&gt;();
            c.Elements("item").ForEach(item =&gt; channel.Items.Add(item.ParseAs&amp;lt;Item&gt;()));
            retVal.Add(channel);                    
        }
    }

    return retVal;
}
&lt;/pre&gt;
&lt;p&gt;Again, I believe the fluent extensions are making our life easier because one logical layer builds on the next. We already have our entities tagged and our parsing worked out, so now we simply iterate the channels and parse those as channels, then iterate the items and parse those as items. Could it be an easier? Now, if I have the text of an RSS feed in a variable called &lt;code&gt;rssFeed&lt;/code&gt;, the only thing I need to do in order to turn it into a list of channels and items is this:
&lt;pre class="brush: csharp;"&gt;
...
var channelList = rssFeed.AsXDocument().AsRssChannelList(); 
...
&lt;/pre&gt;
&lt;p&gt;We've done most of the heavy lifting, so let's tackle actually going out and fetching the feed. If you've worked with Silverlight and tried to fetch any type of information from another website, you'll be familiar with the strict cross-domain policies that Silverlight has. You can read the Microsoft article on &lt;a href="http://msdn.microsoft.com/en-us/library/cc645032(VS.95).aspx" target="_blank"&gt;Network Security Access Restrictions in Silverlight&lt;/a&gt; to get the full scoop. 
&lt;p&gt;In a nutshell, it says most likely we won't be able to reach out from our Silverlight client to touch the RSS feeder and bring back the information. How do you like that twist? Fortunately, there is a workaround.
&lt;p&gt;&lt;b&gt;Using a Handler to Bypass Cross Domain Concerns&lt;/b&gt;
&lt;p&gt;Silverlight is allowed to pull information from the same server that it is hosted from. One simple way to bypass the issue with going out directly from the client to the reader is to create a proxy. We don't have the same restrictions on the server with going across domains, so we can have Silverlight "ask" the server to pull the feed for us, and deliver it back. 
&lt;p&gt;This, however, has its own issues. I can make a handler that takes a Uri and then returns the data, but this would expose a potential security risk in my web application. It would open the door for malicious attackers to hit other websites and make it look like it is coming from my server! It's sort of like the old "call-forwarding" techniques that old school &lt;a href="http://en.wikipedia.org/wiki/Phreaking" target="_blank"&gt;phreakers&lt;/a&gt; would use to hide their illicit telecommunications activities.
&lt;p&gt;I am going to use the handler approach, but make it a little more difficult to abuse. In a production system, I'd implement a full brown encryption scheme. The issue with the Silverlight side is that it gets downloaded to the browser, so a would-be hacker can easily pull apart the code and dissect what's going on. You'll want a fairly strong algorithm to circumvent foul play. For this blog example, I'm going to implement a very light security piece that will thwart any casual foul play by preventing someone from guessing how to pull a feed without knowing the algorithm. OK, so it's not very secret because I'm letting you in on the deal. 
&lt;p&gt;For the sake of illustration, I'm simply going to have the Silverlight client generate a guid, then generate a hash on the GUID using SHA1. Again, for a more secured solution, I'd have a SALT and keywords, etc, but this at least shows a way to secure the communication and should get you thinking about security concerns when you start exposing services for Silverlight to consume. 
&lt;p&gt;In order for this to work, both the client and the server need to implement the same algorithm. I am a big fan of DRY (&lt;a href="http://en.wikipedia.org/wiki/Don't_repeat_yourself" target="_blank"&gt;Don't Repeat Yourself&lt;/a&gt;) so I don't want to duplicate the algorithm in both places. Instead, I'll build this simple piece on the Silverlight side:
&lt;pre class="brush: csharp;"&gt;
public static class SecurityToken
{        
    public static string GenerateToken(string seed)
    {
        Encoder enc = Encoding.Unicode.GetEncoder();

        var unicodeText = new byte[seed.Length * 2];
        enc.GetBytes(seed.ToCharArray(), 0, seed.Length, unicodeText, 0, true);

        System.Security.Cryptography.SHA1 sha = new System.Security.Cryptography.SHA1Managed();

        byte[] result = sha.ComputeHash(unicodeText);

        var sb = new StringBuilder();

        for (int i = 0; i &lt; result.Length; i++)
        {
            sb.Append(result[i].ToString());
        }
        return sb.ToString();

    }        
}
&lt;/pre&gt;
&lt;p&gt;It's a simple method that takes a string and returns the hash as digits. On the web server side, I go into my project and use "add existing item."
&lt;p&gt;&lt;img src="http://gallery.jeremylikness.com/main.php?g2_view=core.DownloadItem&amp;g2_itemId=168&amp;g2_serialNumber=1"/&gt;
&lt;p&gt;Then, I navigate to the security class in my Silverlight project, highlight it, then choose "add as link."
&lt;p&gt;&lt;img src="http://gallery.jeremylikness.com/main.php?g2_view=core.DownloadItem&amp;g2_itemId=170&amp;g2_serialNumber=1"/&gt;
&lt;p&gt;This allows me to share the code between the two sides. I can make a change once and ensure both are always in sync. I call this "poor man's WCF RIA." OK, bad joke. Let's move along. 
&lt;p&gt;In the &lt;code&gt;ClientBin&lt;/code&gt; folder, I add a handler. I do it here because it makes it easy for Silverlight to reference the handler using a relative Uri. Otherwise, I'll have to hack around with the application root and parse strings and do lots of work I just don't care to do. This way, I can reference it as:
&lt;pre class="brush: csharp;"&gt;
...
var handlerUri = new Uri("RssHandler.ashx"); 
...
&lt;/pre&gt;
&lt;p&gt;And be done with it. Silverlight will pass the guid, the key, and the desired Uri. My handler will generate the key from the guid, make sure it matches what was passed, and then proxy the feed. The code looks like this:
&lt;pre class="brush: csharp;"&gt;
[WebService(Namespace = "http://jeremylikness.com/rssReader")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
public class RssHandler : IHttpHandler
{
    public void ProcessRequest(HttpContext context)
    {
        context.Response.ContentType = "text/xml";

        if (context.Request.QueryString["key"].Equals(SecurityToken.GenerateToken(context.Request.QueryString["guid"])))
        {
            using (var client = new WebClient())
            {
                context.Response.Write(client.DownloadString(context.Request.QueryString["rssuri"]));
            }
        }
    }

    public bool IsReusable
    {
        get
        {
            return false;
        }
    }
}
&lt;/pre&gt;
&lt;p&gt;Now we need to the build the service on Silverlight.
&lt;p&gt;&lt;b&gt;The Reader Service&lt;/b&gt;
&lt;p&gt;First, let's start with the interface for the service. What we want is to pass in the URL of the RSS feed, and receive a list of channels with corresponding items that were fetched from the feed. That ends up looking like this: 
&lt;pre class="brush: csharp;"&gt;
public interface IRssReader
{
    void GetFeed(Uri feedUri, Action&amp;lt;List&amp;lt;Channel&gt;&gt; result);
}
&lt;/pre&gt;
&lt;p&gt;Notice I'm making life easy for classes that use the service. They won't have to worry about the asynchronous nature of the service calls or how the result comes back, etc. All that is needed is to pass a method that will accept the list of channels when it becomes available. 
&lt;p&gt;As I mentioned earlier, we already did most of the heavy lifting with parsing out the feed, so wiring in the service is very straightforward. The implementation looks like this:
&lt;pre class="brush: csharp;"&gt;
public class RssReader : IRssReader 
{
    private const string PROXY = "RssHandler.ashx?guid={0}&amp;key={1}&amp;rssuri={2}";

    public void GetFeed(Uri feedUri, Action&amp;lt;List&amp;lt;Channel&gt;&gt; result)
    {

        var client = new WebClient();

        Guid guid = Guid.NewGuid();
       
        client.DownloadStringCompleted += ClientDownloadStringCompleted;
        client.DownloadStringAsync(new Uri(
                                       string.Format(PROXY,
                                                     guid,                                                         
                                                     SecurityToken.GenerateToken(guid.ToString()),
                                                     feedUri), UriKind.Relative), result);
    }

    static void ClientDownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
    {
        var client = sender as WebClient;
        
        if (client != null)
        {
            client.DownloadStringCompleted -= ClientDownloadStringCompleted;
        }

        if (e.Error != null)
        {
            throw e.Error; 
        }

        var result = e.UserState as Action&amp;lt;List&amp;lt;Channel&gt;&gt;; 

        if (result != null)
        {
            result(e.Result.AsXDocument().AsRssChannelList()); 
        }
    }
}
&lt;/pre&gt;
&lt;p&gt;Walking through the steps, we first get the Uri and the method to call when we're done. We wire up a web client and pass it the URL of our handler. This has parameters for the guid and our key, as well as the Uri we want to fetch. We also pass the method to call when we're done. The asynchronous calls all provide a generic object to pass state, so when the call returns we know which version of the call we're dealing with (nice of them, hey?) 
&lt;p&gt;When the call is completed, we unhook the event to avoid any dangling references. If there was an error, we throw it. (Yeah, part of our refactoring in future posts will be dealing with all of the errors I'm either throwing or not catching throughout the example). We take the state object and turn it back into an action, then pass the received value as the list of channels using our fluent extensions.
&lt;p&gt;So now we can get it and load it into our models. We need a view model to host all of this!
&lt;p&gt;&lt;b&gt;The View Model&lt;/b&gt;
&lt;p&gt;For the first pass on this, I'm going to wire everything myself. No fancy PRISM or MEF extensions, we can refactor those later. Let's get to showing something on the screen. 
&lt;p&gt;Our view model should be able to accept the URL of a feed, let the user click "load" and possibly "refresh" on the feed, then show it to us. We want to give them some feedback if the feed isn't a valid Uri, and we probably should keep the load button disabled until there is a valid feed. I ended up creating this for phase one:
&lt;pre class="brush: csharp;"&gt;
public class RssViewModel : INotifyPropertyChanged
{
    private readonly IRssReader _reader; 

    public RssViewModel(IRssReader reader)
    {
        _reader = reader;
        Channels = new ObservableCollection&amp;lt;Channel&gt;();
    }

    private Uri _feedUri;

    private string _uri; 

    public string FeedUri
    {
        get { return _uri; }
        set
        {
            // this will throw an error if invalid, for validation
            _feedUri = new Uri(value);
            _uri = value;
            RaisePropertyChanged("FeedUri");
            RaisePropertyChanged("CanRefresh");
        }
    }

    public bool CanRefresh { get { return _feedUri != null; }}

    public void RefreshCommand()
    {
        if (CanRefresh)
        {
            Channels.Clear();
            _reader.GetFeed(_feedUri, LoadChannels);
        }
    }

    public void LoadChannels(List&amp;lt;Channel&gt; channelList)
    {
        channelList.ForEach(channel=&gt;Channels.Add(channel));
    }

    public ObservableCollection&amp;lt;Channel&gt; Channels { get; set; }

    protected void RaisePropertyChanged(string propertyName)
    {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null)
        {
            handler(this, new PropertyChangedEventArgs(propertyName));
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;
}
&lt;/pre&gt;
&lt;p&gt;The view model implements &lt;code&gt;INotifyPropertyChanged&lt;/code&gt; to support binding. In lieu of using a converter for the Uri, I decided to deal with it as a string, then cast it to a Uri. If the cast fails, it throws an error, so we can use the Silverlight validation engine to display the error. Only if the text was successfully cast to a valid Uri will we enable the refresh button. When it's clicked, we call the service and clear the list of channels, then populate the list on the return call. 
&lt;p&gt;&lt;b&gt;A Basic Page&lt;/b&gt;
&lt;p&gt;Now we can throw together some XAML to show it. In this first iteration I'm not about getting stylish or fancy, so I tossed together something fast. I'm using grids in lieu of stack panels so they auto-size well, and a custom &lt;code&gt;ItemsControl&lt;/code&gt; that allows vertical scroll bars. We simply add the scroll viewer around the items presenter using a style, like this: 
&lt;pre class="brush: xml;"&gt;
&amp;lt;Style 
    TargetType="ItemsControl" 
    BasedOn="{StaticResource ItemsControlStyle}"
    x:Name="ItemsControlOuterStyle"&gt;
    &amp;lt;Setter Property="ItemsControl.Template"&gt;
        &amp;lt;Setter.Value&gt;
            &amp;lt;ControlTemplate&gt;
                &amp;lt;ScrollViewer x:Name="ScrollViewer" Padding="{TemplateBinding Padding}"&gt;
                    &amp;lt;ItemsPresenter /&gt;
                &amp;lt;/ScrollViewer&gt;
            &amp;lt;/ControlTemplate&gt;
        &amp;lt;/Setter.Value&gt;
    &amp;lt;/Setter&gt;            
&amp;lt;/Style&gt;
&lt;/pre&gt;
&lt;p&gt;I know the high priests of MVVM are going to try and burn me for blasphemy with this next move, but we're still in the proof of concept, OK? So far we have no testing, IoC, nor beautiful command extensions. Yes, you are about to see a plain old code-behind event:
&lt;pre class="brush: xml;"&gt;
&amp;lt;TextBlock
    Grid.Column="0"
    Margin="5"
    Text="RSS Feed URL:"/&gt;
&amp;lt;TextBox 
    Grid.Column="1"
    Width="200"
    Margin="5"
    Text="{Binding Path=FeedUri,Mode=TwoWay,NotifyOnValidationError=True,ValidatesOnExceptions=True}"/&gt;
&amp;lt;Button
    Grid.Column="2"
    Margin="5"
    IsEnabled="{Binding Path=CanRefresh}"
    Content="Refresh"
    Click="Button_Click"/&gt;
&lt;/pre&gt;
&lt;p&gt;Here you can enter the feed. When you tab out, it will validate it and show an error if it is invalid. If it passes, the button will be enabled.
&lt;p&gt;This next chunk of XAML shows the items. We'll do more refactoring as well. I will introduce the concept of formatters than will parse things like hyperlinks and Twitter hash terms to provide more interactive functionality, but for now let's just get it out there: 
&lt;pre class="brush: xml;"&gt;
&amp;lt;ItemsControl
    Style="{StaticResource ItemsControlOuterStyle}"
    Grid.Row="1" 
    ItemsSource="{Binding Channels}"&gt;
    &amp;lt;ItemsControl.ItemTemplate&gt;
        &amp;lt;DataTemplate&gt;
            &amp;lt;Grid 
                Margin="5"
                HorizontalAlignment="Stretch"
                VerticalAlignment="Top"&gt;
                &amp;lt;Grid.RowDefinitions&gt;
                    &amp;lt;RowDefinition/&gt;
                    &amp;lt;RowDefinition/&gt;
                    &amp;lt;RowDefinition/&gt;
                &amp;lt;/Grid.RowDefinitions&gt;
                    &amp;lt;HyperlinkButton 
                        Grid.Row="0"
                        Margin="5"
                        FontWeight="Bold"
                        Content="{Binding Title}"
                        NavigateUri="{Binding Link}"/&gt;
                    &amp;lt;TextBlock 
                        Grid.Row="1"
                        Margin="5"
                        TextWrapping="Wrap"
                        Text="{Binding Description}"/&gt;
                &amp;lt;ItemsControl 
                    Grid.Row="2"
                    Style="{StaticResource ItemsControlStyle}"
                    ItemsSource="{Binding Items}"&gt;
                    &amp;lt;ItemsControl.ItemTemplate&gt;
                        &amp;lt;DataTemplate&gt;
                            &amp;lt;Grid HorizontalAlignment="Stretch"
                                  VerticalAlignment="Top"
                                  Margin="5"&gt;
                                &amp;lt;Grid.RowDefinitions&gt;
                                    &amp;lt;RowDefinition/&gt;
                                    &amp;lt;RowDefinition/&gt;
                                &amp;lt;/Grid.RowDefinitions&gt;
                                &amp;lt;Grid.ColumnDefinitions&gt;
                                    &amp;lt;ColumnDefinition Width="Auto"/&gt;
                                    &amp;lt;ColumnDefinition Width="Auto"/&gt;
                                &amp;lt;/Grid.ColumnDefinitions&gt;
                                &amp;lt;TextBlock 
                                    Margin="5"
                                    Grid.Row="0"
                                    Grid.Column="0"
                                    Text="{Binding PublishDate}"/&gt;
                                &amp;lt;HyperlinkButton
                                    Margin="5"
                                    Grid.Row="0"
                                    Grid.Column="1" 
                                    Content="{Binding Title}"
                                    NavigateUri="{Binding Link}"/&gt;
                                &amp;lt;TextBlock 
                                    Grid.Row="1"
                                    Grid.Column="0"
                                    Grid.ColumnSpan="2"
                                    TextWrapping="Wrap"
                                    Text="{Binding Description}"/&gt;
                            &amp;lt;/Grid&gt;
                        &amp;lt;/DataTemplate&gt;
                    &amp;lt;/ItemsControl.ItemTemplate&gt;
                &amp;lt;/ItemsControl&gt;
            &amp;lt;/Grid&gt;                   
        &amp;lt;/DataTemplate&gt;
    &amp;lt;/ItemsControl.ItemTemplate&gt;
&amp;lt;/ItemsControl&gt;
&lt;/pre&gt;
&lt;p&gt;Whew! Now we just need to put in a little bit of code behind. We'll enrage the dependency injection purists by creating hard coded instances and further stoke the ire of MVVM evangelists by wiring in a code behind for the button click: 
&lt;pre class="brush: csharp;"&gt;
public partial class MainPage
{
    public MainPage()
    {
        InitializeComponent();
        LayoutRoot.DataContext = new RssViewModel(new RssReader());
    }

    private void Button_Click(object sender, RoutedEventArgs e)
    {
        ((RssViewModel)LayoutRoot.DataContext).RefreshCommand();
    }
}
&lt;/pre&gt;
&lt;p&gt;Upon publishing and hitting the service, I was able to pull up my Twitter feed:
&lt;p&gt;&lt;img src="http://gallery.jeremylikness.com/main.php?g2_view=core.DownloadItem&amp;g2_itemId=173&amp;g2_serialNumber=2" title="RSS Reader in Silverlight"/&gt;
&lt;p&gt;That's it. Now we have a proof of concept, and it worked. We have a lot more to do ... making it expandable to handle different types of feeds including HTML, styling it, perhaps looking at using multiple feeds, tests, and the lot (yes, I know, I know, the tests should have come earlier). I hope you enjoyed this first look into my process of creating a basic reader and we'll continue to evolve the project with time! 
&lt;p&gt;&lt;a href="http://www.wintellect.com/CS/files/folders/sample_files/entry12050.aspx" target="_blank"&gt;Download the source for this project&lt;/a&gt;
&lt;p&gt;&lt;a href="http://jeremylikness.com/" title="Jeremy Likness"&gt;&lt;img border="0" src="http://jeremylikness.com/signature.gif" alt="Jeremy Likness" title="Jeremy Likness"/&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8944256652433533647-3521709576639163969?l=csharperimage.jeremylikness.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/CSharperImage?a=9_VV_JbrOkU:He2xJhv_-C0:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CSharperImage?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/CSharperImage?a=9_VV_JbrOkU:He2xJhv_-C0:YwkR-u9nhCs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CSharperImage?d=YwkR-u9nhCs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/CSharperImage?a=9_VV_JbrOkU:He2xJhv_-C0:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CSharperImage?i=9_VV_JbrOkU:He2xJhv_-C0:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/CSharperImage?a=9_VV_JbrOkU:He2xJhv_-C0:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CSharperImage?i=9_VV_JbrOkU:He2xJhv_-C0:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/CSharperImage?a=9_VV_JbrOkU:He2xJhv_-C0:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CSharperImage?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/CSharperImage?a=9_VV_JbrOkU:He2xJhv_-C0:I9og5sOYxJI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CSharperImage?d=I9og5sOYxJI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/CSharperImage/~4/9_VV_JbrOkU" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://csharperimage.jeremylikness.com/feeds/3521709576639163969/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://csharperimage.jeremylikness.com/2010/02/fluent-rss-reader-for-silverlight-part.html#comment-form" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8944256652433533647/posts/default/3521709576639163969?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8944256652433533647/posts/default/3521709576639163969?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/CSharperImage/~3/9_VV_JbrOkU/fluent-rss-reader-for-silverlight-part.html" title="A Fluent RSS Reader for Silverlight Part 1: Proof of Concept" /><author><name>Jeremy Likness</name><uri>http://www.blogger.com/profile/18407945801671553594</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="05667915713066003387" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">1</thr:total><feedburner:origLink>http://csharperimage.jeremylikness.com/2010/02/fluent-rss-reader-for-silverlight-part.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CEUERXg7eCp7ImA9WxBWEUg.&quot;"><id>tag:blogger.com,1999:blog-8944256652433533647.post-6572298892376718987</id><published>2010-02-02T18:05:00.001-05:00</published><updated>2010-02-02T18:10:04.600-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-02-02T18:10:04.600-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="unit testing" /><category scheme="http://www.blogger.com/atom/ns#" term="silverlight" /><category scheme="http://www.blogger.com/atom/ns#" term="silverlight unit test" /><category scheme="http://www.blogger.com/atom/ns#" term="moq" /><category scheme="http://www.blogger.com/atom/ns#" term="mocking" /><title>Using Moq with Silverlight for Advanced Unit Tests</title><content type="html">&lt;p&gt;Moq is a library that assists with running unit tests by providing easily mocked objects that implement interfaces and abstract classes. You can learn more about Moq &lt;a href="http://code.google.com/p/moq/" target="_blank"&gt;on their website&lt;/a&gt;. There is a distribution for Silverlight, and in this post I'll focus on some ways to use Moq for some more involved testing scenarios.
&lt;p&gt;&lt;a href="http://www.wintellect.com/CS/files/folders/sample_files/entry11991.aspx" target="_blank"&gt;Download the source code for the example project&lt;/a&gt; 
&lt;p&gt;I started with the &lt;a href="http://csharperimage.jeremylikness.com/2010/01/simple-dialog-service-in-silverlight.html" title="Simple Dialog Service in Silverlight" target="_blank"&gt;Simple Dialog Service in Silverlight&lt;/a&gt; and extended the example a bit. In the post, I promised that abstracting the dialog function behind an interface would facilitate unit testing. In this post, I'll deliver on the promise.
&lt;p&gt;Adhering to the pattern I described in &lt;a href="http://csharperimage.jeremylikness.com/2009/12/simplifying-asynchronous-calls-in.html" target="_blank" title="Simplifying Asynchronous Calls in Silverlight using Action"&gt;Simplifying Asynchronous Calls in Silverlight using Action&lt;/a&gt;, I created the interface for a "Thesaurus" service. In this contrived example, we are showing a list of words. You can highlight a word and see the related synonyms in another list. You may also delete the words from the list. 
&lt;p&gt;Because we assume in the real word that there are thousands upon thousands of available words and synonyms, the view model won't try to hold a complex object graph. I won't have a special "word" entity that has a nested list of synonyms. Instead, I'll maintain two lists: one of words, and one of the current synonyms. The service will be called when a word is selected to retrieve the list of synonyms for that word.
&lt;p&gt;Enough set up ... let's take a refresher and look at the dialog service interface, along with the new thesaurus interface:
&lt;pre class="brush: csharp;"&gt;
public interface IDialogService
{
   void ShowDialog(string title, string message, bool allowCancel, Action&amp;lt;bool&gt; response);
}

public interface IThesaurus
{
    void GetSynonyms(string word, Action&amp;lt;List&amp;lt;string&gt;&gt; result);

    void ListWords(Action&amp;lt;List&amp;lt;string&gt;&gt; result);

    void Delete(string word);
}
&lt;/pre&gt;
&lt;p&gt;As you can see, the interface is straightforward. In the sample project, I've implemented the dialog using the same code as my previous post (which involves a &lt;code&gt;ChildWindow&lt;/code&gt;). The "implementation" of the thesaurus service actually only provides a few words and synonyms but is enough to run the application and see how it would function in the real world.
&lt;p&gt;To run the actual "live" code, right-click on &lt;code&gt;SimpleDialog.Web&lt;/code&gt; and choose "Set as startup project." Then, right-click on &lt;code&gt;SimpleDialogTestPage.aspx&lt;/code&gt; and choose "Set as start page." Hit F5 and you'll be in business. In this screenshot, I've selected a word that we run into quite often in the development world, and you can see that it has synonyms listed for it: 
&lt;p&gt;&lt;img src="http://gallery.jeremylikness.com/main.php?g2_view=core.DownloadItem&amp;g2_itemId=166&amp;g2_serialNumber=1" title="Dogma"/&gt;
&lt;p&gt;The view model is straightforward. It expects an implementation of the dialog service and the thesaurus service, then manages well on its own:
&lt;pre class="brush: csharp;"&gt;
public class ViewModel : INotifyPropertyChanged
{
    private readonly IThesaurus _thesaurus;

    private readonly IDialogService _dialog;

    public ViewModel()
    {
        Words = new ObservableCollection&amp;lt;string&gt;();
        Synonyms = new ObservableCollection&amp;lt;string&gt;();
       
        DeleteCommand = new DelegateCommand&amp;lt;object&gt;( o=&gt;ConfirmDelete(), o=&gt;!string.IsNullOrEmpty(CurrentWord));
    }

   public ViewModel(IThesaurus thesaurus, IDialogService dialogService) : this()
    {
        _thesaurus = thesaurus;
        _dialog = dialogService;

        _thesaurus.ListWords(PutWords); 
    }

    public DelegateCommand&amp;lt;object&gt; DeleteCommand { get; set; }

    public ObservableCollection&amp;lt;string&gt; Words { get; set; }

    public void PutWords(List&amp;lt;string&gt; words)
    {
        Words.Clear();
        foreach(string word in words)
        {
            Words.Add(word);
        }

        // default first word
        if (Words.Count &gt; 0)
        {
            CurrentWord = Words[0]; 
        }
    }

    public ObservableCollection&amp;lt;string&gt; Synonyms { get; set; }

    public void PutSynonyms(List&amp;lt;string&gt; synonyms)
    {
        Synonyms.Clear();
        foreach (string synonym in synonyms)
        {
            Synonyms.Add(synonym);
        }
    }

    public void ConfirmDelete()
    {
        _dialog.ShowDialog("Confirm Delete", string.Format("Do you really want to delete {0}?", CurrentWord),
            true, b =&gt;
                      {
                          if (b)
                          {
                              _thesaurus.Delete(CurrentWord);
                              _thesaurus.ListWords(PutWords);
                          }
                      });
    }

    private string _currentWord = string.Empty; 

    public string CurrentWord
    {
        get { return _currentWord; }
        set
        {
            _currentWord = value;
            _thesaurus.GetSynonyms(value, PutSynonyms);
            OnPropertyChanged("CurrentWord");
            DeleteCommand.RaiseCanExecuteChanged();
        }
    }

    protected void OnPropertyChanged(string propertyName)
    {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null)
        {
            handler(this, new PropertyChangedEventArgs(propertyName));
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;
}
&lt;/pre&gt;
&lt;p&gt;Let's walk through it briefly. The constructor initializes the lists and the delete command, which requires that there is a &lt;code&gt;CurrentWord&lt;/code&gt; selected. When the services are passed in, it requests the list of words and asks the service to call &lt;code&gt;PutWords&lt;/code&gt; with the list. This will load the results and set a default "current word" based on the first item in the list.
&lt;p&gt;The current word is interesting, because when it is set, it goes out to request a list of synonyms. This is populated to the synonym list. When the view model is constructed and the list of words is received, it will automatically fire a request for the synonyms by setting the current word. The current word also updates the &lt;code&gt;DeleteCommand&lt;/code&gt; so it can be enabled or disabled based on whether or not a word is currently selected.
&lt;p&gt;The delete command itself calls the dialog service for confirmation, and only if the user confirms will it then call the service, delete the word, and then request a new list of words. 
&lt;p&gt;This view model is written so that I need almost zero code behind in my user control. The XAML looks like this, and is driven completely by data-binding:
&lt;pre class="brush: xml;"&gt;
&amp;lt;UserControl x:Class="SimpleDialog.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
    xmlns:cal="clr-namespace:Microsoft.Practices.Composite.Presentation.Commands;assembly=Microsoft.Practices.Composite.Presentation"
    mc:Ignorable="d" d:DesignWidth="640" d:DesignHeight="480"&gt;
  &amp;lt;Grid x:Name="LayoutRoot" 
        HorizontalAlignment="Center"
        VerticalAlignment="Center"&gt;
        &amp;lt;Grid.RowDefinitions&gt;
            &amp;lt;RowDefinition/&gt;
            &amp;lt;RowDefinition/&gt;
        &amp;lt;/Grid.RowDefinitions&gt;
        &amp;lt;Grid.ColumnDefinitions&gt;
            &amp;lt;ColumnDefinition/&gt;
            &amp;lt;ColumnDefinition/&gt;
        &amp;lt;/Grid.ColumnDefinitions&gt; 
        &amp;lt;ListBox 
            HorizontalAlignment="Center"
            VerticalAlignment="Center"
            ItemsSource="{Binding Words}"
            SelectedItem="{Binding CurrentWord, Mode=TwoWay}"
            SelectionMode="Single"
            Grid.Row="0"
            Grid.Column="0"/&gt;
        &amp;lt;ListBox
            HorizontalAlignment="Center"
            VerticalAlignment="Center"            
            Width="Auto"
            ItemsSource="{Binding Synonyms}"
            Grid.Row="0"
            Grid.Column="1"/&gt;
        &amp;lt;Button 
            HorizontalAlignment="Center"
            VerticalAlignment="Center"            
            Width="Auto"
            Content="Delete"
            Grid.Row="1"
            Grid.Column="0"
            cal:Click.Command="{Binding DeleteCommand}"/&gt;
  &amp;lt;/Grid&gt;
&amp;lt;/UserControl&gt;

&lt;/pre&gt;
&lt;p&gt;The key here is the bindings from the delete button to the delete command, and the list box of words to the "current word." This allows all of the other updates to cascade accordingly. I said I had "almost no" code behind. This is because I'm traveling light and decided not to drag an IoC container into the example. Therefore, in the code behind, I manually wire up the view model like this: 
&lt;pre class="brush: csharp;"&gt;
public MainPage()
{
    InitializeComponent();
    DataContext = new ViewModel(new Thesaurus(), new DialogService());
}  
&lt;/pre&gt;
&lt;p&gt;Now that we've set the stage, the real focus of this post is how to test what we've just created. I have a view model that does quite a bit, and want to make sure it is behaving. To make this happen, I'll do two things. First, I'll add the Silverlight Unit Testing Framework. I first discussed it in my post about &lt;a href="http://csharperimage.jeremylikness.com/2009/12/unit-tests-for-viewmodels-and-views-in.html" target="_blank" title="Silverlight Unit Testing for Views and View Models"&gt;unit testing views AND view models&lt;/a&gt;. Next, I'll navigate to the Moq page and download the Silverlight bits (all of this is included in the reference project). 
&lt;p&gt;My test class is "view model tests." The first thing I need to do is set up some support for the tests. We want a pretend list of words and synonyms, and mocks for the services the view model depends on. Our class starts out like this:
&lt;pre class="brush: csharp;"&gt;
[TestClass]
public class ViewModelTests
{
    private readonly List&amp;lt;string&gt; _words = new List&amp;lt;string&gt; {"test", "mock"};

    private readonly List&amp;lt;string&gt; _synonyms = new List&amp;lt;string&gt; {"evaluation", "experiment"};

    private readonly List&amp;lt;String&gt; _mockSynonyms = new List&amp;lt;string&gt; {"counterfeit", "ersatz", "pseudo", "substitute"};

    private Mock&amp;lt;IDialogService&gt; _dialogMock;

    private Mock&amp;lt;IThesaurus&gt; _thesaurusMock;

    private ViewModel _target;
}
&lt;/pre&gt;
&lt;p&gt;We created two words with synonym lists. The mocking of the services is as simple as declaring &lt;code&gt;Mock&amp;lt;T&gt;&lt;/code&gt;. There is more to it that we'll cover, but this gets us started. I like to always have a reference to the object I am testing as &lt;code&gt;target&lt;/code&gt; to make it clear what the test is run for.
&lt;p&gt;Now we will need to set up the view model for all of our tests. Just like with the standard unit testing framework, we can flag a method as &lt;code&gt;TestInitialize&lt;/code&gt; to do set up before each test is run. Take a look at my setup: 
&lt;pre class="brush: csharp;"&gt;
[TestInitialize]
public void InitializeTests()
{
    _dialogMock = new Mock&amp;lt;IDialogService&gt;();

    _thesaurusMock = new Mock&amp;lt;IThesaurus&gt;();

    _thesaurusMock.Setup(
        t =&gt; t.ListWords(It.IsAny&amp;lt;Action&amp;lt;List&amp;lt;string&gt;&gt;&gt;()))
        .Callback((Action&amp;lt;List&amp;lt;string&gt;&gt; action) =&gt; action(_words));

    _thesaurusMock.Setup(
        t =&gt; t.GetSynonyms(It.Is((string s) =&gt; s.Equals(_words[0])), It.IsAny&amp;lt;Action&amp;lt;List&amp;lt;string&gt;&gt;&gt;()))
        .Callback((string word, Action&amp;lt;List&amp;lt;string&gt;&gt; action) =&gt; action(_synonyms));

    _thesaurusMock.Setup(
        t =&gt; t.GetSynonyms(It.Is((string s) =&gt; s.Equals(_words[1])), It.IsAny&amp;lt;Action&amp;lt;List&amp;lt;string&gt;&gt;&gt;()))
        .Callback((string word, Action&amp;lt;List&amp;lt;string&gt;&gt; action) =&gt; action(_mockSynonyms));

    _target = new ViewModel(_thesaurusMock.Object, _dialogMock.Object);
}
&lt;/pre&gt; 
&lt;p&gt;We create a new mock for every test so the internal counters are reset. Then, it gets a little interesting. The setup command allows you to determine what an expected call will be, and to provide results. Many methods return values, and there is a &lt;code&gt;Result&lt;/code&gt; method to use for providing what those values should be. In our case, however, the methods do not return anything because they call the &lt;code&gt;Action&lt;/code&gt; when complete. Therefore, we set up a callback so that we can perform an action when the method is fired.
&lt;p&gt;To see how that works, take a look at the first set up. We are setting up our mock for the thesaurus service. The lambda expression indicates we expect the &lt;code&gt;ListWords&lt;/code&gt; to be called, and the parameter can be any action that acts on a list of a strings. Now the important part: the callback. The callback has the same signature as the method. When the method is called, Moq will fire the callback and send the parameters. In our case, we take the action that was passed in, and call it with our list of words. This will mock the process of the view model requesting the word list, then having the &lt;code&gt;PutWords&lt;/code&gt; method called with the actual list.
&lt;p&gt;Next, we set up the &lt;code&gt;GetSynonyms&lt;/code&gt; method twice. This is because we want to pass a different result based on the word that the method is called with. Instead of &lt;code&gt;IsAny&lt;/code&gt;, we'll use &lt;code&gt;Is&lt;/code&gt; with a lambda that determines what will pass. In this way, we can compare specific values or even ranges. If the passed value is the first word, we call the action with the synonym list. If the passed value is the second word ("mock"), we call the action with the list of mocks. If any other value is passed in, we simply don't care so we haven't set that up.
&lt;p&gt;The first test we'll make is for setup. In other words, after the view model is constructed, we simply want to test that everything was set up appropriately. The view model promises to provide us with lists and commands, so we need to ensure these will be available when we bind to it.
&lt;pre class="brush: csharp;"&gt;
[TestMethod]
public void TestConstructor()
{
    // make sure it made the call
    _thesaurusMock.Verify(t =&gt; t.ListWords(_target.PutWords), Times.Exactly(1),
                          "List words method was not called.");
    _thesaurusMock.Verify(
        t =&gt; t.GetSynonyms(It.Is((string s) =&gt; s.Equals(_words[0])), It.IsAny&amp;lt;Action&amp;lt;List&amp;lt;string&gt;&gt;&gt;()),
        Times.Exactly(1),
        "Synonym method never called for first word.");
    Assert.AreEqual(_target.CurrentWord, _words[0], "View model did not default target word.");
    Assert.IsNotNull(_target.DeleteCommand, "Delete command was not initialized.");
    Assert.IsTrue(_target.DeleteCommand.CanExecute(null),
                  "Delete command is disabled when selected word exists.");
    CollectionAssert.AreEquivalent(_words, _target.Words, "Words do not match.");
    CollectionAssert.AreEquivalent(_synonyms, _target.Synonyms, "Synonyms do not match.");
}
&lt;/pre&gt;
&lt;p&gt;The setup commands "rigged" what we expect when a method is called. If these were the only actions we took, this would really be a "stub" (something there to make it happen) rather than a mock (something that changes and can be inspected after the test to determine the outcome). With Moq, we use verify to inspect the state of the mocked object. First, we verify that the word list was called exactly once. Next, we verify that the synonym list was called specifically with the first word. Next, we are comparing values, lists, and commands to make sure they are as we expect. For example, the view model should have already populated a list of synonyms that matches the first word, so we use the &lt;code&gt;CollectionAssert&lt;/code&gt; to make sure the lists are equivalent.
&lt;p&gt;Now we can do a little more in depth test. Let's test selection. When we select the second word by setting the &lt;code&gt;CurrentWord&lt;/code&gt; property, the view model should call the thesaurus service to retrieve the list of synonyms for 'mock.' The test looks like this:
&lt;pre class="brush: csharp;"&gt;
[TestMethod]
public void TestSelection()
{
    _target.CurrentWord = _words[1]; 

    CollectionAssert.AreEquivalent(_mockSynonyms, _target.Synonyms, "Synonyms did not update.");
}
&lt;/pre&gt;
&lt;p&gt;Technically, I could have verified the call as well and if you feel that is necessary, then by all means include that test. In this case, I know the synonym list simply won't update itself, so if it ends up changing to the list I'm expected, I'm confident that the call took place. Therefore, I simply test that the mock synonyms were updated to the collection of synonyms on the view model.
&lt;p&gt;What about a more complicated test? Our delete command requires confirmation, so the user doesn't accidentally delete a word they did not intend to. Therefore, we need to set up the dialog service to return the results we want. We'll have two tests: one that ensures the delete service is called when the user confirms, and another that ensures it is NOT called when the user cancels. The confirm test looks like this:
&lt;pre class="brush: csharp;"&gt;
[TestMethod]
public void TestDeleteConfirm()
{
    _thesaurusMock.Setup(t =&gt; t.Delete(It.IsAny&amp;lt;string&gt;())); 

    _dialogMock.Setup(
        d =&gt; d.ShowDialog(It.IsAny&amp;lt;string&gt;(),
                          It.IsAny&amp;lt;string&gt;(),
                          It.IsAny&amp;lt;bool&gt;(),
                          It.IsAny&amp;lt;Action&amp;lt;bool&gt;&gt;()))
        .Callback(
        (string title, string message, bool cancel, Action&amp;lt;bool&gt; action) =&gt; action(true));

    _target.DeleteCommand.Execute(null);

    _thesaurusMock.Verify(
        t =&gt; t.Delete(It.Is((string s) =&gt; s.Equals(_words[0]))),
        Times.Exactly(1),
        "The delete method was not called on the service.");
}

&lt;/pre&gt;
&lt;p&gt;First we set up the service to expect the delete call. Next, we set up the dialog. We don't care about the parameters passed in. All we care about is that we call the action with "true" to simulate a user confirming the dialog. Once this is set up, we trigger the delete command, and verify that the delete service was called for the appropriate word.
&lt;p&gt;For the cancel, we pass false in the action, and use &lt;code&gt;Times.Never()&lt;/code&gt; on the method signature to ensure the delete service was not called. 
&lt;p&gt;Finally, because our delete command is only enabled when a current word is selected, we need to test that it is disabled with no words:
&lt;pre class="brush: csharp;"&gt;
[TestMethod]
public void TestDeleteEnabled()
{
    _target.CurrentWord = string.Empty; 

    Assert.IsFalse(
        _target.DeleteCommand.CanExecute(null),
        "Delete command did not disable with empty word selection.");
}
&lt;/pre&gt;
&lt;p&gt;We already tested for the positive case in the constructor. Now, we simply clear the selection and confirm that the command is no longer allowed to execute.
&lt;p&gt;If you ran the application earlier, you simply need to set the "test" project as the start-up project to run the unit tests. They will run directly in the browser.
&lt;p&gt;As you can see, using the MVVM pattern appropriately ensures straightforward XAML (mostly binding-driven without cluttered code-behind) and very granular testing. Tools like Moq can make it much easier to test complicated scenarios by allowing you to easily set up dependencies, mock returns, and ultimately validate that the view model is behaving the way it is expected to.
&lt;p&gt;&lt;a href="http://www.wintellect.com/CS/files/folders/sample_files/entry11991.aspx" target="_blank"&gt;Download the source code for the example project&lt;/a&gt; 
&lt;p&gt;&lt;a href="http://jeremylikness.com/" title="Jeremy Likness"&gt;&lt;img border="0" src="http://jeremylikness.com/signature.gif" alt="Jeremy Likness" title="Jeremy Likness"/&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8944256652433533647-6572298892376718987?l=csharperimage.jeremylikness.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/CSharperImage?a=m1AHvhhnWdA:MEgj3eaSPxE:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CSharperImage?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/CSharperImage?a=m1AHvhhnWdA:MEgj3eaSPxE:YwkR-u9nhCs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CSharperImage?d=YwkR-u9nhCs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/CSharperImage?a=m1AHvhhnWdA:MEgj3eaSPxE:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CSharperImage?i=m1AHvhhnWdA:MEgj3eaSPxE:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/CSharperImage?a=m1AHvhhnWdA:MEgj3eaSPxE:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CSharperImage?i=m1AHvhhnWdA:MEgj3eaSPxE:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/CSharperImage?a=m1AHvhhnWdA:MEgj3eaSPxE:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CSharperImage?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/CSharperImage?a=m1AHvhhnWdA:MEgj3eaSPxE:I9og5sOYxJI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CSharperImage?d=I9og5sOYxJI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/CSharperImage/~4/m1AHvhhnWdA" height="1" width="1"/&gt;</content><link rel="related" href="http://code.google.com/p/moq/" title="Using Moq with Silverlight for Advanced Unit Tests" /><link rel="replies" type="application/atom+xml" href="http://csharperimage.jeremylikness.com/feeds/6572298892376718987/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://csharperimage.jeremylikness.com/2010/02/using-moq-with-silverlight-for-advanced.html#comment-form" title="3 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8944256652433533647/posts/default/6572298892376718987?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8944256652433533647/posts/default/6572298892376718987?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/CSharperImage/~3/m1AHvhhnWdA/using-moq-with-silverlight-for-advanced.html" title="Using Moq with Silverlight for Advanced Unit Tests" /><author><name>Jeremy Likness</name><uri>http://www.blogger.com/profile/18407945801671553594</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="05667915713066003387" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">3</thr:total><feedburner:origLink>http://csharperimage.jeremylikness.com/2010/02/using-moq-with-silverlight-for-advanced.html</feedburner:origLink></entry><entry gd:etag="W/&quot;Ak4ASXY4fyp7ImA9WxBXGEw.&quot;"><id>tag:blogger.com,1999:blog-8944256652433533647.post-4199556127407564481</id><published>2010-01-29T21:35:00.000-05:00</published><updated>2010-01-29T21:35:48.837-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-01-29T21:35:48.837-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="video" /><category scheme="http://www.blogger.com/atom/ns#" term="silverlight" /><category scheme="http://www.blogger.com/atom/ns#" term="encoding" /><category scheme="http://www.blogger.com/atom/ns#" term="smooth streaming" /><category scheme="http://www.blogger.com/atom/ns#" term="media" /><category scheme="http://www.blogger.com/atom/ns#" term="live smooth streaming" /><title>Programmatically Accessing the Live Smooth Streaming API</title><content type="html">&lt;p&gt;&lt;a href="http://www.iis.net/expand/LiveSmoothStreaming" target="_blank" title="Live Smooth Streaming"&gt;Live Smooth Streaming&lt;/a&gt; is a Microsoft technology that allows you to take a live, encoded, incoming video stream and rebroadcast it using &lt;a href="http://www.iis.net/expand/SmoothStreaming" target="_blank" title="Smooth Streaming"&gt;Smooth Streaming&lt;/a&gt; technology. This technology multicasts the video stream in segments of varying bandwidths. This can then be played with a Silverlight-based client like the built-in &lt;code&gt;MediaElement&lt;/code&gt; or more advanced player like the &lt;a href="http://smf.codeplex.com/" target="_blank" title="Silverlight Media Framework"&gt;Silverlight Media Framework&lt;/a&gt;. 
&lt;p&gt;The incoming streams could be from your web cam or third party sources, or even from a file encoded on disk that is being webcast at a particular point in time. The live smooth streaming allows the client to adjust to the current network load and gracefully degrade quality when the network slows to avoid having to pause the playback and force the user to wait for a new buffer. The user can also rewind the "live content," and there are options to archive it to play on demand at a later date. 
&lt;p&gt;A content network with many live streams might have multiple servers and cabinets in their data centers to serve content. In that scenario, programmatic management of endpoints becomes essential to effectively scale the operation. If you find yourself needing to automate some aspects of starting, stopping, shutting down or creating publishing points for live streaming, you're in luck! 
&lt;p&gt;Let's start with a few entities to help us handle publishing points. A publishing point can have a stream state (the status of the encoding stream it is listening to), and archive state (the status of the stream it is archiving to) and a fragment stream that enables insertion of other content to the stream. These various nodes on the publishing point share a common set of states:
&lt;pre class="brush: csharp;"&gt;

public enum State
{
    Disabled,
    Started,
    Stopped,
    Unknown
}

&lt;/pre&gt;
&lt;p&gt;These are fairly self-explanatory. "Unknown" simply means the publishing point is in a status, such as stopped or shut down, when it doesn't make sense for the node to have a valid status.
&lt;p&gt;The publishing point itself has a more involved list of states. For an excellent overview, read &lt;a href="http://learn.iis.net/page.aspx/622/live-smooth-streaming-for-iis-70---creating-and-managing-publishing-points/" target="_blank"&gt;this article on creating and managing publishing points&lt;/a&gt;. Here are the states:
&lt;pre class="brush: csharp;"&gt;

public enum PublishingPointState
{
    Idle,
    Starting,
    Started,
    Stopping,
    Stopped,
    Shuttingdown,
    Error,
    Unknown
}

&lt;/pre&gt;
&lt;p&gt;Again, these are fairly self-explanatory. Idle happens when the publishing point has been created, but no action has been taken against it, or it is shut down. Starting indicates it is ready to receive a feed, and started means it is actively processing one. 
&lt;p&gt;Let's go ahead and build an entity to represent the publishing point:
&lt;pre class="brush: csharp;"&gt;

public class PublishingPoint
{        
    public State StreamState { get; set; }

    public State ArchiveState { get; set; }

    public State FragmentState { get; set; }

    public PublishingPointState PubState { get; set; }

    public string SiteName { get; set; }

    public string Path { get; set; }

    public string Name { get; set; }
}
&lt;/pre&gt;
&lt;p&gt;The first few properties are the various states of the nodes and the publishing point itself. The site name is the website it is configured on. This will usually be "Default Web Site." The Path is the virtual path (not the physical path) the publishing point resides in (also known as the &lt;code&gt;Application&lt;/code&gt;), and the name is the actual name of the publishing point.
&lt;p&gt;While there is not a strongly typed API to interface directly with the live smooth streaming configuration as of this writing, we can easily reach it through the new administration classes. With IIS 7.0 and smooth streaming installed, you should be able to find &lt;code&gt;Microsoft.Web.Administration.dll&lt;/code&gt; in your &lt;code&gt;%windir%\system32\inetsrv&lt;/code&gt; directory. Reference this DLL, and you can programmatically access web sites. You can also interact with configurations through a reflection-style interface that we'll cover here. 
&lt;p&gt;&lt;b&gt;Get the List of Publishing Points&lt;/b&gt;
&lt;p&gt;Our first task is to get a list of publishing points.
&lt;pre class="brush: csharp;"&gt;

private const string LIVESTREAMINGSECTION = "system.webServer/media/liveStreaming";
private const string METHODGETPUBPOINTS = "GetPublishingPoints";
private const string ATTR_SITENAME = "siteName";
private const string ATTR_VIRTUALPATH = "virtualPath";
private const string ATTR_NAME = "name";
private const string ATTR_ARCHIVES = "archives";
private const string ATTR_FRAGMENTS = "fragments";
private const string ATTR_STREAMS = "streams";
private const string ATTR_STATE = "state";
        
public List&amp;lt;PublishingPoint&gt; GetPublishingPoints()
{
    var retVal = new List&amp;lt;PublishingPoint&gt;();

    using (var serverManager = new ServerManager())
    {
        Configuration appHost = serverManager.GetApplicationHostConfiguration();

        try
        {
            ConfigurationSection liveStreamingConfig = appHost.GetSection(LIVESTREAMINGSECTION);

            foreach (Site site in serverManager.Sites)
            {
                foreach (Application application in site.Applications)
                {
                    try
                    {
                        ConfigurationMethodInstance instance =
                            liveStreamingConfig.Methods[METHODGETPUBPOINTS].CreateInstance();

                        instance.Input[ATTR_SITENAME] = site.Name;
                        instance.Input[ATTR_VIRTUALPATH] = application.Path;

                        instance.Execute();

                        ConfigurationElement collection = instance.Output.GetCollection();

                        foreach (var item in collection.GetCollection())
                        {
                            retVal.Add(new PublishingPoint
                                           {
                                               SiteName = site.Name,
                                               Path = application.Path,
                                               Name = item.Attributes[ATTR_NAME].Value.ToString(),
                                               ArchiveState = (State) item.Attributes[ATTR_ARCHIVES].Value,
                                               FragmentState = (State) item.Attributes[ATTR_FRAGMENTS].Value,
                                               StreamState = (State) item.Attributes[ATTR_STREAMS].Value,
                                               PubState =
                                                   (PublishingPointState) item.Attributes[ATTR_STATE].Value
                                           });
                        }
                    }
                    catch (COMException ce)
                    {
                        Debug.Print(ce.Message);
                    }
                }
            }
        }
        catch (COMException ce)
        {
            Debug.Print(ce.Message);
        }
    }

    return retVal;
}
&lt;/pre&gt;
&lt;p&gt;The &lt;code&gt;ServerManager&lt;/code&gt; is our hook into administration. All of the configuration for the live smooth streaming is in the &lt;code&gt;APPHOST&lt;/code&gt; section of the configuration, which we fetch at the beginning of the method by grabbing the configuration and then navigating to &lt;code&gt;system.webServer/media/liveStreaming&lt;/code&gt;.
&lt;p&gt;The method to fetch publishing points requires a web site and an application (virtual directory). We iterate through these and use the &lt;code&gt;ConfigurationMethodInstance&lt;/code&gt; to ask for the this. The new IIS configuration extensions allow methods and API hook points to be defined in the configuration itself, with a set of inputs and outputs. You can read more about the &lt;a href="http://msdn.microsoft.com/en-us/library/microsoft.web.administration.configurationmethod.aspx" target="_blank"&gt;ConfigurationMethod&lt;/a&gt;. We use this and pass in the web site name and application, to receive the list of publishing points. Notice how we get a generic collection of &lt;code&gt;ConfigurationElement&lt;/code&gt; and reference the attributes to build our more strongly-typed &lt;code&gt;PublishingPoint&lt;/code&gt; object.
&lt;p&gt;Of course, there are multiple areas where exceptions may be thrown. In the example, I capture the COM errors and just print them to debug. You can interrogate the error code and provide more specific feedback as to why the call failed. 
&lt;p&gt;&lt;b&gt;Starting, Stopping, and Shutting Down Publishing Points&lt;/b&gt;
&lt;p&gt;Now that we have a publishing point, we can stop, start, and shut it down. This is also done through a configuration method. The method names for the action are: 
&lt;pre class="brush: csharp;"&gt;

public enum PublishingPointCommand
{
    Start,
    Stop,
    Shutdown
}

&lt;/pre&gt;
&lt;p&gt;The method names are the actual text, so we can use the &lt;code&gt;ToString()&lt;/code&gt; method on the enum to pass the command. Issuing a command against a specific publishing point now looks like this: 
&lt;pre class="brush: csharp;"&gt;

private static void _IssueCommand(PublishingPoint publishingPoint, PublishingPointCommand command)
{
    using (var serverManager = new ServerManager())
    {
        Configuration appHost = serverManager.GetApplicationHostConfiguration();

        ConfigurationSection liveStreamingConfig = appHost.GetSection(LIVESTREAMINGSECTION);

        if (liveStreamingConfig == null)
        {
            throw new Exception("Couldn't get to the live streaming section.");
        }

        ConfigurationMethodInstance instance =
            liveStreamingConfig.Methods[METHODGETPUBPOINTS].CreateInstance();

        instance.Input[ATTR_SITENAME] = publishingPoint.SiteName;
        instance.Input[ATTR_VIRTUALPATH] = publishingPoint.Path;

        instance.Execute();

        // Gets the PublishingPointCollection associated with the method output
        ConfigurationElement collection = instance.Output.GetCollection();

        foreach (var item in collection.GetCollection())
        {
            if (item.Attributes[ATTR_NAME].Value.ToString().Equals(publishingPoint.Name))
            {
                var method = item.Methods[command.ToString()];
                var methodInstance = method.CreateInstance();
                methodInstance.Execute();
                break;
            }
        }
    }
}

&lt;/pre&gt;
&lt;p&gt;Of course, you can probably see a place where it makes sense to refactor some code, because we're spinning through the collection again. This time, instead of turning it into a concrete type, we are taking the specific item in the collection for the publishing point we're targeting, then creating an instance of the command method and firing it off. Simple as that! 
&lt;p&gt;&lt;b&gt;Creating the Publishing Point&lt;/b&gt;
&lt;p&gt;So now we can manipulate and gather information about a point, but what about creating it? If you are frustrated trying to find where in the API you can call a "Create" method, take a deep breath and step away from the configuration collection. It's not there. To create a publishing point, we simply drop a file on the system! That's right. If you create a new publishing point, you can navigate to the file system and set an &lt;code&gt;.isml&lt;/code&gt; file. Open it in notepad and you'll find the format is straightforward:
&lt;pre class="brush: xml;"&gt;
&amp;lt;?xml version="1.0" encoding="utf-8"?&gt;
   &amp;lt;smil xmlns="http://www.w3.org/2001/SMIL20/Language"&gt;
      &amp;lt;head&gt;
         &amp;lt;meta name="title" content="Pub Point Title" /&gt;
         &amp;lt;meta name="module" content="liveSmoothStreaming" /&gt;
         &amp;lt;meta name="sourceType" content="Push" /&gt;&amp;lt;!-- or Pull --&gt;
         &amp;lt;meta name="publishing" content="Fragments;Streams;Archives" /&gt;
         &amp;lt;meta name="estimatedTime" content="00:11:22" /&gt;
         &amp;lt;meta name="lookaheadChunks" content="2" /&gt;
         &amp;lt;meta name="manifestWindowLength" content="0" /&gt;
         &amp;lt;meta name="startOnFirstRequest" content="False" /&gt;
         &amp;lt;meta name="archiveSegmentLength" content="0" /&gt;
      &amp;lt;/head&gt;
   &amp;lt;body/&gt;
&amp;lt;/smil&gt;
&lt;/pre&gt;
&lt;p&gt;That's it ... very straightforward. Give it a title, make it push or pull, and estimate the time. Of course, you can manipulate some of the more advanced features as well, but for a basic interface, this is all we need. We'll store the XML with a constant that holds the template called &lt;code&gt;ISML_TEMPLATE&lt;/code&gt;. When the user requests a new publishing point, we'll find the right virtual directory, get the physical path, and then write out the file:
&lt;pre class="brush: csharp;"&gt;
public enum LiveSourceType
{
    Push,
    Pull
}

public bool CreatePublishingPoint(PublishingPoint publishingPoint, string title, string duration, LiveSourceType type)
{

    bool retVal = false;

    using (var manager = new ServerManager())
    {
        Site site = manager.Sites[publishingPoint.SiteName];

        Application application = site.Applications[publishingPoint.Path];

        string template =
            string.Format(ISML_TEMPLATE, title, type, duration ?? string.Empty);

        try
        {
            string path = string.Format(@"{0}\{1}", application.VirtualDirectories[0].PhysicalPath,
                                        publishingPoint.Name);

            File.WriteAllText(path, template);

            retVal = true;
        }
        catch (Exception ex)
        {
            Debug.Print(ex.Message);
        }
    }

    return retVal;
}
&lt;/pre&gt;
&lt;p&gt;This is fairly straightforward to give you the point. In production, you'll need to test for nulls (i.e. if the site doesn't exist, a null template is passed in, etc) and may want to validate that it was created successfully by enumerating the list after creation. I'd also recommend creating an &lt;code&gt;XmlDocument&lt;/code&gt; or &lt;code&gt;XDocument&lt;/code&gt; for more advanced titles ... in this example, using string format, we can make it fast but must make sure the title is clean or escape it before making it part of the source XML. 
&lt;p&gt;That's it ... in a nutshell, you now have all of the bits and pieces needed to interface programmatically with the Live Smooth Streaming APIs. I have no sample project because this is intended to be a guideline for your own explorations and use of the system. I would also suggest the excellent blog by &lt;a href="http://blogs.southworks.net/ejadib/" target="_blank"&gt;Ezequiel Jadib&lt;/a&gt; which contains loads of information about smooth streaming. 
&lt;p&gt;&lt;a href="http://jeremylikness.com/" title="Jeremy Likness"&gt;&lt;img border="0" src="http://jeremylikness.com/signature.gif" alt="Jeremy Likness" title="Jeremy Likness"/&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8944256652433533647-4199556127407564481?l=csharperimage.jeremylikness.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/CSharperImage?a=GN0B5BOuRCU:1gSJJgGcqNY:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CSharperImage?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/CSharperImage?a=GN0B5BOuRCU:1gSJJgGcqNY:YwkR-u9nhCs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CSharperImage?d=YwkR-u9nhCs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/CSharperImage?a=GN0B5BOuRCU:1gSJJgGcqNY:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CSharperImage?i=GN0B5BOuRCU:1gSJJgGcqNY:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/CSharperImage?a=GN0B5BOuRCU:1gSJJgGcqNY:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CSharperImage?i=GN0B5BOuRCU:1gSJJgGcqNY:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/CSharperImage?a=GN0B5BOuRCU:1gSJJgGcqNY:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CSharperImage?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/CSharperImage?a=GN0B5BOuRCU:1gSJJgGcqNY:I9og5sOYxJI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CSharperImage?d=I9og5sOYxJI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/CSharperImage/~4/GN0B5BOuRCU" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://csharperimage.jeremylikness.com/feeds/4199556127407564481/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://csharperimage.jeremylikness.com/2010/01/programmatically-accessing-live-smooth.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8944256652433533647/posts/default/4199556127407564481?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8944256652433533647/posts/default/4199556127407564481?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/CSharperImage/~3/GN0B5BOuRCU/programmatically-accessing-live-smooth.html" title="Programmatically Accessing the Live Smooth Streaming API" /><author><name>Jeremy Likness</name><uri>http://www.blogger.com/profile/18407945801671553594</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="05667915713066003387" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://csharperimage.jeremylikness.com/2010/01/programmatically-accessing-live-smooth.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CkEMRnwyfyp7ImA9WxBXFkk.&quot;"><id>tag:blogger.com,1999:blog-8944256652433533647.post-5702205225275832621</id><published>2010-01-27T19:54:00.003-05:00</published><updated>2010-01-27T20:04:47.297-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-01-27T20:04:47.297-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="silverlight" /><category scheme="http://www.blogger.com/atom/ns#" term="debugging" /><category scheme="http://www.blogger.com/atom/ns#" term="windbg" /><title>Introduction to Debugging Silverlight Applications with WinDbg</title><content type="html">&lt;p&gt;I've had a few users ask me about finding memory leaks and understanding what happens with references in Silverlight. One very powerful tool to use when debugging Silverlight applications is the Windows Debugging Tools. You can download the &lt;a href="http://www.microsoft.com/whdc/devtools/debugging/installx86.mspx#a" target="_blank" title="32-bit Windows Debugging Tools"&gt;32-bit (x86) version&lt;/a&gt; side-by-side with the &lt;a href="http://www.microsoft.com/whdc/devtools/debugging/install64bit.mspx#" target="_blank" title="64-bit Windows Debugging Tools"&gt;64-bit (x64) version&lt;/a&gt;.
&lt;p&gt;&lt;img src="http://jeremylikness.com/video/silverlight-debugging-with-windbg/WinDbg_Thumb.jpg"/&gt;
&lt;p&gt;Both WPF and Silverlight ship with an extension DLL you can load called SOS. This extension contains &lt;a href="http://msdn.microsoft.com/en-us/library/bb190764(VS.80).aspx" target="_blank" title="SOS Debugging Extension"&gt;many powerful commands&lt;/a&gt;.
&lt;p&gt;In the video, &lt;a href="http://jeremylikness.com/video/silverlight-debugging-with-windbg/" target="_blank" title="Silverlight Debugging with WinDBG"&gt;Silverlight Debugging with WinDbg&lt;/a&gt; (30 minutes long), I walk through a debugging scenario using my &lt;a href="http://csharperimage.jeremylikness.com/2009/12/fractal-koch-snowflakes-in-silverlight.html" target="_blank" title="Fractal Koch Snowflakes in Silverlight"&gt;Fractal Koch Snowflakes&lt;/a&gt;. 
&lt;p&gt;I show how to dump the heap, walk object references, see which references are targetted for garbage collection and which ones still have root references, examine event handlers and delegates to trace back to the target methods, an unroll lists and arrays. It's sort of a "firehose" approach but with a real world example that I hope helps drive home how powerful it can be.
&lt;p&gt;Watch the video by &lt;a href="http://jeremylikness.com/video/silverlight-debugging-with-windbg/"&gt;clicking here&lt;/a&gt; (30 minutes).
&lt;p&gt;&lt;a href="http://jeremylikness.com/" title="Jeremy Likness"&gt;&lt;img border="0" src="http://jeremylikness.com/signature.gif" alt="Jeremy Likness" title="Jeremy Likness"/&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8944256652433533647-5702205225275832621?l=csharperimage.jeremylikness.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/CSharperImage?a=6XbWYp6svTY:4QF2EDlynh4:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CSharperImage?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/CSharperImage?a=6XbWYp6svTY:4QF2EDlynh4:YwkR-u9nhCs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CSharperImage?d=YwkR-u9nhCs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/CSharperImage?a=6XbWYp6svTY:4QF2EDlynh4:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CSharperImage?i=6XbWYp6svTY:4QF2EDlynh4:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/CSharperImage?a=6XbWYp6svTY:4QF2EDlynh4:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CSharperImage?i=6XbWYp6svTY:4QF2EDlynh4:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/CSharperImage?a=6XbWYp6svTY:4QF2EDlynh4:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CSharperImage?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/CSharperImage?a=6XbWYp6svTY:4QF2EDlynh4:I9og5sOYxJI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CSharperImage?d=I9og5sOYxJI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/CSharperImage/~4/6XbWYp6svTY" height="1" width="1"/&gt;</content><link rel="related" href="http://jeremylikness.com/video/silverlight-debugging-with-windbg/" title="Introduction to Debugging Silverlight Applications with WinDbg" /><link rel="replies" type="application/atom+xml" href="http://csharperimage.jeremylikness.com/feeds/5702205225275832621/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://csharperimage.jeremylikness.com/2010/01/introduction-to-debugging-silverlight.html#comment-form" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8944256652433533647/posts/default/5702205225275832621?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8944256652433533647/posts/default/5702205225275832621?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/CSharperImage/~3/6XbWYp6svTY/introduction-to-debugging-silverlight.html" title="Introduction to Debugging Silverlight Applications with WinDbg" /><author><name>Jeremy Likness</name><uri>http://www.blogger.com/profile/18407945801671553594</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="05667915713066003387" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">2</thr:total><feedburner:origLink>http://csharperimage.jeremylikness.com/2010/01/introduction-to-debugging-silverlight.html</feedburner:origLink></entry><entry gd:etag="W/&quot;AkcMRHszeSp7ImA9WxBXEks.&quot;"><id>tag:blogger.com,1999:blog-8944256652433533647.post-2096808777263265359</id><published>2010-01-23T10:28:00.007-05:00</published><updated>2010-01-23T12:34:45.581-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-01-23T12:34:45.581-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="silverlight" /><category scheme="http://www.blogger.com/atom/ns#" term="asynchronous" /><category scheme="http://www.blogger.com/atom/ns#" term="dialog" /><title>Simple Dialog Service in Silverlight</title><content type="html">&lt;p&gt;I noticed on the forums there are a lot of users not comfortable with asynchronous programming who struggle a bit in Silverlight with getting their arms around the concept of a dialog box. In other environments, you can simply shoot out a dialog, wait for the response, and continue. In Silverlight, of course, the action is asynchronous. I would argue it should be this way most of the time. 
&lt;p&gt;The problem is that many people tend to take the approach of trying to force the process into a synchronous one, instead of changing the way they think and approach the application. There is a reason why processes are asynchronous in Silverlight. There is one main UI thread, and a blocking process would block the entire thread and effectively freeze the Silverlight application. Having the process asynchronous allows you to continue to render graphics elements, perform actions in the background, even display a soothing animation while you await the user's response.
&lt;p&gt;I spoke to a more highly decoupled approach in a post awhile ago that was more an experiment with the event aggregator: &lt;a href="http://csharperimage.jeremylikness.com/2009/09/decoupled-childwindow-dialogs-with.html" target="_blank"&gt;Decoupled Child Window Dialogs with Silverlight and PRISM&lt;/a&gt;. Here, I want to show the more straightforward approach.
&lt;p&gt;The first step is to choose what the dialog will be displayed with. In Silverlight, the &lt;code&gt;ChildWindow&lt;/code&gt; makes perfect sense because it is a modal dialog that appears, waits for the user response, and then saves the response. We'll create a new child window and call it &lt;code&gt;Dialog.xaml&lt;/code&gt;. It looks like this:
&lt;pre class="brush: xml;"&gt;
&amp;lt;controls:ChildWindow x:Class="SimpleDialog.Dialog"
           xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
           xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
           xmlns:controls="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls"
           Width="400" Height="300" 
           Title="{Binding Title}"&gt;
    &amp;lt;Grid x:Name="LayoutRoot" Margin="2"&gt;
        &amp;lt;Grid.RowDefinitions&gt;
            &amp;lt;RowDefinition /&gt;
            &amp;lt;RowDefinition Height="Auto" /&gt;
        &amp;lt;/Grid.RowDefinitions&gt;
        &amp;lt;TextBlock TextWrapping="Wrap" Grid.Row="0" Text="{Binding Message}"/&gt;
        &amp;lt;Button x:Name="CancelButton" Content="Cancel" Click="CancelButton_Click" Width="75" Height="23" HorizontalAlignment="Right" Margin="0,12,0,0" Grid.Row="1" /&gt;
        &amp;lt;Button x:Name="OKButton" Content="OK" Click="OKButton_Click" Width="75" Height="23" HorizontalAlignment="Right" Margin="0,12,79,0" Grid.Row="1" /&gt;
    &amp;lt;/Grid&gt;
&amp;lt;/controls:ChildWindow&gt;
&lt;/pre&gt;
&lt;p&gt;You'll notice I made very few changes from the provided template. The key here is that I changed the title to bind with the &lt;code&gt;Title&lt;/code&gt; property, and added a text block to display a message from the &lt;code&gt;Message&lt;/code&gt; property.
&lt;p&gt;Because this is a simple dialog box, I really feel a view model is overkill. Some purists will insist on this but I argue the functionality is simple enough that we don't need the extra overhead. We'll be using an interface to the solution down the road that we can easily unit test, and this makes the dialog function (which lives entirely in the UI) a self-contained implementation.
&lt;p&gt;Next, I made a few changes to the code behind:
&lt;pre class="brush: csharp;"&gt;
public partial class Dialog : ChildWindow
{
    public Action&amp;lt;bool&gt; CloseAction { get; set; }

    public static readonly DependencyProperty MessageProperty = DependencyProperty.Register(
        "Message",
        typeof(string),
        typeof(Dialog),
        null);


    public string Message
    {
        get { return GetValue(MessageProperty).ToString(); }
        set { SetValue(MessageProperty, value); }
    }

    public Dialog()
    {
        InitializeComponent();
        DataContext = this;
    }        

    public Dialog(bool allowCancel)
        : this()
    {
        CancelButton.Visibility = allowCancel ? Visibility.Visible : Visibility.Collapsed;
    }

    private void OKButton_Click(object sender, RoutedEventArgs e)
    {
        this.DialogResult = true;            
    }

    private void CancelButton_Click(object sender, RoutedEventArgs e)
    {
        this.DialogResult = false;           
    }
}
&lt;/pre&gt;
&lt;p&gt;Again, not too many changes here. I added the &lt;code&gt;Message&lt;/code&gt; property as a dependency property, and in the constructor I set the data context to itself. This allows me to bind to the title and message. This allows us to simply set the message on the dialog and have it appear. I also added an action for it to retain when closed. This will store a callback so that it can notify the host of the user's final actions. Finally, there is a method that conditions whether or not there is the option for a cancel button. For alerts, we'll simply show an OK button. For confirmations, we'll show the Cancel button as well.
&lt;p&gt;Next is a simple interface to the dialog. Nothing in our application should know or care how the dialog is displayed. There is simply a mechanism to display the dialog and possibly acquire a response. The interface looks like this:
&lt;pre class="brush: csharp;"&gt;
public interface IDialogService
{
    void ShowDialog(string title, string message, bool allowCancel, Action&amp;lt;bool&gt; response);
}
&lt;/pre&gt;
&lt;p&gt;In our simple demonstration, I'm allowing for a title, a message, whether or not you want to show the cancel button for confirmations, and then an action to call with the response. With this simple interface we have all we need to wire in unit tests for services and controls that rely on the dialog. You can create your own mock object that implements the &lt;code&gt;IDialogService&lt;/code&gt; interface and returns whatever response you want to stage for the unit test.
&lt;p&gt;In the production application, we'll need to show a real dialog. Here is the class that handles it:
&lt;pre class="brush: csharp;"&gt;
public class DialogService : IDialogService
{
    #region IDialogService Members

    public void ShowDialog(string title, string message, bool allowCancel, Action&amp;lt;bool&gt; response)
    {
        var dialog = new Dialog(allowCancel) {Title = title, Message = message, CloseAction = response};
        dialog.Closed += DialogClosed;
        dialog.Show();
    }

    static void DialogClosed(object sender, EventArgs e)
    {
        var dialog = sender as Dialog;
        if (dialog != null)
        {
            dialog.Closed -= DialogClosed; 
            dialog.CloseAction(dialog.DialogResult == true);
        }
    }

    #endregion
}
&lt;/pre&gt;
&lt;p&gt;This is fairly straightforward. When called, we'll create an instance of the dialog and set the various properties, including the callback. We wire into the closed event. Whether the user responds by clicking a button or closing the dialog, this event is fired.
&lt;p&gt;There is a reason why we are using the snippet &lt;code&gt;DialogResult == true&lt;/code&gt;. The result is null-able, so we cannot simply refer to the value itself and make a true/false decision (null, by definition, is unknown). So only if the user explicitly provides a true response by clicking the OK button will the expression evaluate to true. Otherwise, we assume false and call back with the response.
&lt;p&gt;There is also a very important step here that is important to recognize. Many beginners fail to catch this subtle step and end up with memory leaks. When the closed event fires, the dialog box effectively closes. Typically, there would be no more references to it (it is no longer in the visual tree) and it can be cleaned up by garbage collection. However, there is a fatal mistake you can make that will result in the dialog box never going away.
&lt;p&gt;That mistake has to do with how events work. When we register the closed event, the thought process is often that the dialog box has an event, and therefore knows to call back to the dialog service. This is flawed, however. A reference exists from the dialog service to the dialog box. The dialog service effectively "listens" for the event, and when it is raised, will respond. We must unregister the event like this:
&lt;p&gt;&lt;code&gt;dialog.Closed -= DialogClosed;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Otherwise, the reference remains and garbage collection will never claim the dialog box resource. In a long running application, this could prove to be a serious flaw. &lt;b&gt;This line is not included in the code sample download.&lt;/b&gt; I encourage you to run with &lt;code&gt;windbg&lt;/code&gt; or even step through debug in Visual Studio and watch the object graphs and reference counts as you fire multiple dialogs. Then, add the line of code above and re-run it to see the difference when you appropriately unregister the event.
&lt;p&gt;To demonstrate the use of the service, I put together a quick little page with a few buttons and a text block:
&lt;pre class="brush: xml;"&gt;
&amp;lt;UserControl x:Class="SimpleDialog.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
    mc:Ignorable="d" d:DesignWidth="640" d:DesignHeight="480"&gt;
  &amp;lt;Grid x:Name="LayoutRoot"&gt;
        &amp;lt;StackPanel Orientation="Vertical"&gt;
            &amp;lt;Button x:Name="ToggleEnabled" 
                    HorizontalAlignment="Center"
                    Margin="5" Width="Auto" Content="Disable Dialog Button" Click="ToggleEnabled_Click"/&gt;
            &amp;lt;Button x:Name="DialogButton" 
                    HorizontalAlignment="Center"
                    Margin="5" Width="Auto" Content="DialogButton" Click="DialogButton_Click"/&gt;
            &amp;lt;TextBlock x:Name="TextDialog" 
                       HorizontalAlignment="Center"
                       Margin="5" Width="Auto" Text="Result Will Show Here"/&gt;
        &amp;lt;/StackPanel&gt;
    &amp;lt;/Grid&gt;
&amp;lt;/UserControl&gt;
&lt;/pre&gt;
&lt;p&gt;The first button is a toggle to enable or disable the second button. It shows how to receive a response and act based on the user input. If the user confirms, the button is toggled to enabled or disabled. If the user cancels or closes the dialog, the state of the button remains the same. The second button raises a dialog, and simply shows the result. Because it is an alert dialog, we know a false response indicates the user closed the window instead of clicking OK.
&lt;p&gt;Here is the code behind:
&lt;pre class="brush: csharp;"&gt;
public partial class MainPage : UserControl
{
    private bool _toggleState = true;
    private readonly IDialogService _dialog = new DialogService();

    public MainPage()
    {
        InitializeComponent();
    }

    private void ToggleEnabled_Click(object sender, RoutedEventArgs e)
    {
        _dialog.ShowDialog(
            _toggleState ? "Disable Button" : "Enable Button",
            _toggleState
                ? "Are you sure you want to disable the dialog button?"
                : "Are you sure you want to enable the dialog button?",
            true,
            r =&gt;
                {
                    if (r)
                    {
                        _toggleState = !_toggleState;
                        DialogButton.IsEnabled = _toggleState;
                        ToggleEnabled.Content = _toggleState ? "Disable Dialog Button" : "Enable Dialog Button";
                    }
                });
    }

    private void DialogButton_Click(object sender, RoutedEventArgs e)
    {
        _dialog.ShowDialog(
            "Confirm This",
            "You have to either close the window or click OK to confirm this.",
            false,
            r =&gt; { TextDialog.Text = r ? "You clicked OK." : "You closed the dialog."; });
    }
}
&lt;/pre&gt;
&lt;p&gt;Notice that in the click events, we call to the dialog service and pass it anonymous methods for the return types. We could point to real methods on the class as well. The important part is to change your thought process from synchronous step one =&gt; wait =&gt; step two to asynchronous step one =&gt; delegate to step two, then step two is called when ready. 
&lt;p&gt;In a production application, instead of creating an instance of the dialog box, we would either register it with a container:
&lt;p&gt;&lt;code&gt;Container.RegisterInstance&amp;lt;IDialogService&gt;(Container.Resolve&amp;lt;DialogService&gt;());&lt;/code&gt;
&lt;p&gt;And inject it in a constructor, or use something like MEF and import the dialog service:
&lt;pre class="brush: csharp;"&gt;
[Import]
public IDialogService Dialog { get; set; }
&lt;/pre&gt;
&lt;p&gt;We would simply flag the implementation as the export or use the &lt;code&gt;InheritedExport&lt;/code&gt; attribute on the interface itself.
&lt;p&gt;&lt;a href="http://www.wintellect.com/CS/files/folders/sample_files/entry11889.aspx" target="_blank"&gt;Click here to download the source code for this example&lt;/a&gt;.
&lt;p&gt;&lt;a href="http://jeremylikness.com/" title="Jeremy Likness"&gt;&lt;img border="0" src="http://jeremylikness.com/signature.gif" alt="Jeremy Likness" title="Jeremy Likness"/&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8944256652433533647-2096808777263265359?l=csharperimage.jeremylikness.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/CSharperImage?a=bx0b6BUyXuE:BvAZi4s7Ua8:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CSharperImage?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/CSharperImage?a=bx0b6BUyXuE:BvAZi4s7Ua8:YwkR-u9nhCs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CSharperImage?d=YwkR-u9nhCs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/CSharperImage?a=bx0b6BUyXuE:BvAZi4s7Ua8:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CSharperImage?i=bx0b6BUyXuE:BvAZi4s7Ua8:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/CSharperImage?a=bx0b6BUyXuE:BvAZi4s7Ua8:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CSharperImage?i=bx0b6BUyXuE:BvAZi4s7Ua8:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/CSharperImage?a=bx0b6BUyXuE:BvAZi4s7Ua8:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CSharperImage?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/CSharperImage?a=bx0b6BUyXuE:BvAZi4s7Ua8:I9og5sOYxJI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CSharperImage?d=I9og5sOYxJI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/CSharperImage/~4/bx0b6BUyXuE" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://csharperimage.jeremylikness.com/feeds/2096808777263265359/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://csharperimage.jeremylikness.com/2010/01/simple-dialog-service-in-silverlight.html#comment-form" title="3 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8944256652433533647/posts/default/2096808777263265359?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8944256652433533647/posts/default/2096808777263265359?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/CSharperImage/~3/bx0b6BUyXuE/simple-dialog-service-in-silverlight.html" title="Simple Dialog Service in Silverlight" /><author><name>Jeremy Likness</name><uri>http://www.blogger.com/profile/18407945801671553594</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="05667915713066003387" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">3</thr:total><feedburner:origLink>http://csharperimage.jeremylikness.com/2010/01/simple-dialog-service-in-silverlight.html</feedburner:origLink></entry><entry gd:etag="W/&quot;D04MQHcyeip7ImA9WxBQGUQ.&quot;"><id>tag:blogger.com,1999:blog-8944256652433533647.post-7951188802162025119</id><published>2010-01-20T08:49:00.003-05:00</published><updated>2010-01-20T08:59:41.992-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-01-20T08:59:41.992-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="silverlight 3.0.50106.0" /><category scheme="http://www.blogger.com/atom/ns#" term="silverlight" /><category scheme="http://www.blogger.com/atom/ns#" term="silverlight 3" /><title>New Silverlight 3 Version Released (3.0.50106.0)</title><content type="html">&lt;p&gt;A new version of Silverlight 3 has been released.
&lt;p&gt;You can download the latest control &lt;a href="http://www.microsoft.com/silverlight/get-started/install/default.aspx" target="_blank"&gt;here&lt;/a&gt;. If you are a developer, then you'll want to use the developer installer that is available &lt;a href="http://go2.microsoft.com/fwlink/?LinkID=150228" target="_blank"&gt;here&lt;/a&gt;.
&lt;p&gt;This version fixes some issues related to hardware acceleration in the graphics processing unit (GPU), certain cases that cause Deep Zoom to take on high CPU, and issues with downloads from Silverlight applications.
&lt;p&gt;Read Microsoft's Knowledge Base article for this release: &lt;a href="http://support.microsoft.com/kb/979202" title="Silverlight 3.0.50106.0 Release Details" target="_blank"&gt;Description of the update for Silverlight: January 19, 2010&lt;/a&gt;.
&lt;p&gt;&lt;a href="http://jeremylikness.com/" title="Jeremy Likness"&gt;&lt;img border="0" src="http://jeremylikness.com/signature.gif" alt="Jeremy Likness" title="Jeremy Likness"/&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8944256652433533647-7951188802162025119?l=csharperimage.jeremylikness.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/CSharperImage?a=K9iopbf6SOI:dYdJvcuCQwA:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CSharperImage?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/CSharperImage?a=K9iopbf6SOI:dYdJvcuCQwA:YwkR-u9nhCs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CSharperImage?d=YwkR-u9nhCs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/CSharperImage?a=K9iopbf6SOI:dYdJvcuCQwA:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CSharperImage?i=K9iopbf6SOI:dYdJvcuCQwA:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/CSharperImage?a=K9iopbf6SOI:dYdJvcuCQwA:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CSharperImage?i=K9iopbf6SOI:dYdJvcuCQwA:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/CSharperImage?a=K9iopbf6SOI:dYdJvcuCQwA:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CSharperImage?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/CSharperImage?a=K9iopbf6SOI:dYdJvcuCQwA:I9og5sOYxJI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CSharperImage?d=I9og5sOYxJI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/CSharperImage/~4/K9iopbf6SOI" height="1" width="1"/&gt;</content><link rel="related" href="http://www.microsoft.com/silverlight/get-started/install/default.aspx" title="New Silverlight 3 Version Released (3.0.50106.0)" /><link rel="replies" type="application/atom+xml" href="http://csharperimage.jeremylikness.com/feeds/7951188802162025119/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://csharperimage.jeremylikness.com/2010/01/new-silverlight-3-version-released.html#comment-form" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8944256652433533647/posts/default/7951188802162025119?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8944256652433533647/posts/default/7951188802162025119?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/CSharperImage/~3/K9iopbf6SOI/new-silverlight-3-version-released.html" title="New Silverlight 3 Version Released (3.0.50106.0)" /><author><name>Jeremy Likness</name><uri>http://www.blogger.com/profile/18407945801671553594</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="05667915713066003387" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">1</thr:total><feedburner:origLink>http://csharperimage.jeremylikness.com/2010/01/new-silverlight-3-version-released.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DUUDQ3g5fip7ImA9WxBQFkg.&quot;"><id>tag:blogger.com,1999:blog-8944256652433533647.post-6557735635764111573</id><published>2010-01-16T10:50:00.000-05:00</published><updated>2010-01-16T10:54:32.626-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-01-16T10:54:32.626-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="MEF" /><category scheme="http://www.blogger.com/atom/ns#" term="inversion of control" /><category scheme="http://www.blogger.com/atom/ns#" term="windsor" /><category scheme="http://www.blogger.com/atom/ns#" term="dependency injection" /><category scheme="http://www.blogger.com/atom/ns#" term="unity framework" /><title>Making Your Own 8K Homegrown Inversion of Control Container</title><content type="html">&lt;p&gt;If you develop software, chances are you you've worked with Inversion of Control containers and the Dependency Injection pattern. Many frameworks exist to address how to marry concrete implementations to abstract classes and interfaces. A few popular ones on the .NET platform include:
&lt;ul&gt;&lt;li&gt;&lt;a href="http://code.google.com/p/autofac/" target="_blank" title="Autofac"&gt;Autofac&lt;/a&gt;&lt;li&gt;&lt;a href="http://www.castleproject.org/castle/download.html" target="_blank" title="Castle Windsor"&gt;Castle Windsor&lt;/a&gt;&lt;li&gt;&lt;a href="http://www.codeplex.com/MEF" target="_blank" title="Managed Extensibility Framework"&gt;Managed Extensibility Framework (MEF)&lt;/a&gt;&lt;li&gt;&lt;a href="http://ninject.org/" target="_blank" title="Ninject"&gt;Ninject&lt;/a&gt;&lt;li&gt;&lt;a href="http://structuremap.sourceforge.net/Default.htm" target="_blank" title="StructureMap"&gt;StructureMap&lt;/a&gt;&lt;li&gt;&lt;a href="http://www.codeplex.com/unity/" target="_blank" title="Unity"&gt;Unity&lt;/a&gt;&lt;/ul&gt;
&lt;p&gt;&lt;a href="http://www.wintellect.com/CS/files/folders/sample_files/entry11579.aspx" target="_blank"&gt;Download the Source for this Example&lt;/a&gt;
&lt;p&gt;There are a few reasons why I decided to play with the concept of building my own dependency injection solution. First, I am never content to just "talk to the framework." I like to know "what lies beneath." With so many open source projects, it's not difficult to go behind the scenes and understand just how these frameworks are glued together. Second, sometimes a larger framework in a smaller project just doesn't make sense (sort of like hitting a tack with a sledgehammer) so understanding some principles of how to roll my own lightweight container will come in handy. Of course, I could also just bust out a simple Service Locater or Factory and achieve similar results, so that brings me to my third point: it's fun.
&lt;p&gt;What I managed to throw together was and 8K DLL that performs auto-discovery. Nothing fancy here. It simply scans the assemblies you send it for concrete implementations of interfaces and types you ask for. Again, this is more of an exercise of pulling back the cover and looking inside the CLR than an attempt to rival the robust, mature frameworks out there. 
&lt;p&gt;The result doesn't support generics, isn't attribute-based, doesn't have support for lifetime management (i.e. singletons), doesn't have named containers and doesn't perform stable composition. It does, however, do the trick of marrying a simple implementation to an interface or an abstract class and knows how to hierarchically wire up dependencies as deep as it needs to go. 
&lt;p&gt;With this small solution, I was able to make a simple call to a method on an interface:
&lt;pre class="brush: csharp;"&gt;

...
ResolverEngine.Resolve&amp;lt;ICoordinator&gt;().Coordinate();
...

&lt;/pre&gt;
&lt;p&gt;And also loop through several implementations of another interface:
&lt;pre class="brush: csharp;"&gt;

...
ResolverEngine.ResolveAll&amp;lt;IPlugin&gt;().ForEach(p =&gt; p.DoSomething());   
...

&lt;/pre&gt;
&lt;p&gt;So how do we go from an interface to the actual implementation of that interface, and create an instance of a class that might have multiple parameters in a constructor we don't know about before hand? 
&lt;p&gt;The way I decided to implement this was to store references to the assemblies we want to scan for dependencies (so that we're not inspecting &lt;code&gt;mscorlib&lt;/code&gt; if we don't need to, for example), to resolve on demand but cache the resolutions for future look ups. 
&lt;p&gt;From that information, we can at least start with our assembly cache and our type-mapper cache (think of an interface or base class type mapping to multiple implementation types).
&lt;pre class="brush: csharp;"&gt;

private static readonly List&amp;lt;Assembly&gt; _assemblyCache = new List&amp;lt;Assembly&gt;();
private static readonly Dictionary&amp;lt;Type, List&amp;lt;Type&gt;&gt; _typeCache = new Dictionary&amp;lt;Type, List&amp;lt;Type&gt;&gt;();

&lt;/pre&gt;
&lt;p&gt;Now for the resolver. Here's something interesting to sort out: generics only work on an actual type, not a variable pointing to a type. In other words:
&lt;pre class="brush: csharp;"&gt;

// this is fine
IGenericInterface&amp;lt;MyClass&gt; myClassInterface = Factory.GetInterface&amp;lt;MyClass&gt;();

// this is not valid
Type type = typeof(MyClass); 
IGenericInterface&amp;lt;type&gt; myClassInterface = Factory.GetInterface&amp;lt;type&gt;(); 

&lt;/pre&gt;
&lt;p&gt;To be able to recursively resolve dependencies (for example, when constructor injection is used), we'll need to support the explicit runtime type name. Therefore, our shell for the resolve method ends up looking like this:
&lt;pre class="brush: csharp;"&gt;

public static T Resolve&amp;lt;T&gt;() where T : class
{
    return Resolve(typeof(T).AssemblyQualifiedName) as T;
}

public static object Resolve(string type) 
{
    Type srcType = Type.GetType(type);
    ...
}

&lt;/pre&gt;
&lt;p&gt;Now we can use the generic call or the runtime call without issue. 
&lt;p&gt;The algorithm to resolve the type has two parts.
&lt;p&gt;The first part determines how to map the current type to an implemented type. If the current type is a class then it's simple: we want to instantiate it. If the current type is an interface or a base class, we need to scan the registered assemblies to find types that implement the base class or interface. We need to make sure they are public and not static. 
&lt;p&gt;The second part scans the type for the most verbose constructor (we don't have to do it this way, but its the way many IoC containers work so I decided to implement it like this). Once we find the most verbose constructor, we need to recursively resolve the types specified in the constructor and then activate the instance with those parameters.
&lt;p&gt;Let's filter the types first.
&lt;pre class="brush: csharp;"&gt;

private static Type[] _FilterTypes(Type srcType, Assembly a)
{
    return a.GetTypes().Where(
                t =&gt; t.IsClass &amp;&amp; t.IsPublic &amp;&amp; !t.IsAbstract &amp;&amp; !t.IsInterface &amp;&amp; 
                    (srcType.IsInterface &amp;&amp; t.GetInterface(srcType.FullName) != null
                    || srcType.IsAbstract &amp;&amp; t.IsSubclassOf(srcType))
                ).ToArray();
}

&lt;/pre&gt;
&lt;p&gt;This reads "scan the assembly for all types that are public classes, are not abstract or interfaces, and either implement the source interface or derive from the base class."
&lt;p&gt;Once we have the mapped type, we need to find the most verbose constructor and then recursively satisfy the dependencies. The &lt;code&gt;_Activate&lt;/code&gt; method does this for us:
&lt;pre class="brush: csharp;"&gt;

private static object _Activate(Type t)
{
    object retVal = null; 

    // find the main constructor
    ConstructorInfo ci = (from c in t.GetConstructors() 
              orderby c.GetParameters().Length descending 
              where c.IsPublic &amp;&amp; !c.IsStatic
              select c).FirstOrDefault();

    if (ci != null)
    {
        if (ci.GetParameters().Length == 0)
        {
            retVal = Activator.CreateInstance(t);
        }
        else
        {
            ParameterInfo[] parameterInfo = ci.GetParameters();

            object[] parameters = new object[parameterInfo.Length];

            int parameterIndex = 0;
            foreach (ParameterInfo parameter in parameterInfo)
            {
                parameters[parameterIndex++] = Resolve(parameter.ParameterType.AssemblyQualifiedName);
            }

            retVal = Activator.CreateInstance(t, parameters);
        }
    }
    return retVal; 
}

&lt;/pre&gt;
&lt;p&gt;We grab the constructors that aren't static and are public. If we have none or the one we find has no parameters, we simply activate the instance. Otherwise, we build an object collection and recursively resolve the dependencies, adding the resolved instances to the collection. We then activate the instance by passing in the collection, which finds and applies the collection to the appropriate constructor.
&lt;p&gt;Now, we can back up to our resolution method and expand it:
&lt;pre class="brush: csharp;"&gt;

public static object Resolve(string type) 
{
    Type srcType = Type.GetType(type);

    if (srcType == null || (!srcType.IsClass &amp;&amp; !srcType.IsInterface &amp;&amp; !srcType.IsAbstract))
    {
        throw new ArgumentException("type"); 
    }

    object retVal = null;

    if (!srcType.IsInterface &amp;&amp; !srcType.IsAbstract)
    {
        retVal = _Activate(srcType);
    }
    else if (_typeCache.ContainsKey(srcType))
    {
        retVal = _Activate(_typeCache[srcType][0]);
    }
    else
    {
        foreach (Assembly a in _assemblyCache)
        {
            // get the mappable types in the assembly 
            foreach(Type t in _FilterTypes(srcType, a))
            {
                // activate and cache it
                object instance = _ActivateAndCache(srcType, t);       
         
                // if we were able to activate and it is appropriate, load it up
                if (instance != null)
                {
                    // finally, return value is the first type we come across
                    retVal = retVal ?? instance;
                }
            }
        }

    }
    return retVal; 
}

&lt;/pre&gt;
&lt;p&gt;We check the type to make sure it is valid. If it's a class type, we simply activate it. If it is an abstract class or interface, we first check the cache and take the first mapping (again, this is where frameworks offer much more because you can explicitly map &lt;i&gt;which&lt;/i&gt; type you want, in our case to simplify we just grab the first available). If it's not in the cache, we get all of the types and insert them into the cache with &lt;code&gt;_ActivateAndCache&lt;/code&gt;.
&lt;p&gt;The &lt;code&gt;_ActivateAndCache&lt;/code&gt; method does a reality check on the instance to make sure it is assignable from the interface or abstract class. Only if this passes does it return the instance and cache it:
&lt;pre class="brush: csharp;"&gt;

object retVal = null;

object instance = _Activate(t);                 
     
if (instance != null &amp;&amp; srcType.IsAssignableFrom(instance.GetType()))
{
   retVal = instance;
   // cache it
}

return retVal; 

&lt;/pre&gt;
&lt;p&gt;At this stage we've pretty much built all we need. The &lt;code&gt;RegisterAssembly&lt;/code&gt; method does a little bit more than just store the assembly reference. Because we may have already cached a type, when a new assembly is registered we'll need to scan the existing types and then add any implementations of those types from the new assembly. That code looks like this:
&lt;pre class="brush: csharp;"&gt;

public static void RegisterAssembly(Assembly assembly)
{
    bool resolve = false; 

    lock (_assemblyCache)
    {
        if (!_assemblyCache.Contains(assembly))
        {
            _assemblyCache.Add(assembly);
            resolve = true;
        }                               
    }

    if (resolve)
    {
        foreach (Type type in _typeCache.Keys)
        {
            foreach (Type t in _FilterTypes(type, assembly))
            {
                _ActivateAndCache(type, t);
            }
        }
    }            
}

&lt;/pre&gt;
&lt;p&gt;Finally, I added a few methods to resolve all instances instead of just one.
&lt;p&gt;Where does that leave us? The test project introduces two very simple interfaces:
&lt;pre class="brush: csharp;"&gt;

public interface IPlugin
{
    void DoSomething();
}

public interface ICoordinator
{
    void Coordinate();
}

&lt;/pre&gt;
&lt;p&gt;In an implementation project, I set up a straightforward implementation of &lt;code&gt;IPlugin&lt;/code&gt;, then a base class that implements the interface and another class that derives from the base class. This is all completely contrived to demonstrate what the resolver can do:
&lt;pre class="brush: csharp;"&gt;

public class Plugin1 : IPlugin
{
    public void DoSomething()
    {
        Console.WriteLine("This is the first plugin.");
    }

}

public abstract class PluginBase : IPlugin
{

    public virtual void DoSomething()
    {
        Console.WriteLine("You found me."); 
    }

}

public class PluginMain : PluginBase
{
    public override void DoSomething()
    {
        Console.WriteLine("This is the override, now calling base class.");
        base.DoSomething();
    }
}

&lt;/pre&gt;
&lt;p&gt;The coordinate class demonstrates how the resolver will recursively resolve dependencies. It takes in the interface as well as the base class:
&lt;pre class="brush: csharp;"&gt;

public class Coordinator : ICoordinator
{
    IPlugin _interface;
    PluginBase _base;

    public Coordinator()
    {
    }

    public Coordinator(IPlugin interfaceInstance, PluginBase impl)
    {
        _interface = interfaceInstance;
        _base = impl;
    }

    public void Coordinate()
    {
        Console.WriteLine("Interface:");
        _interface.DoSomething();

        Console.WriteLine("Base class:"); 
        _base.DoSomething();
    }

}

&lt;/pre&gt;
&lt;p&gt;Finally, I put another implementation of the plugin to the main program to show how it doesn't resolve until that assembly is added. With all of these together, the main thread looks like this:
&lt;pre class="brush: csharp;"&gt;

static void Main(string[] args)
{
    ResolverEngine.RegisterAssembly(typeof(PluginMain).Assembly);

    Console.WriteLine("Coordinator...");

    ResolverEngine.Resolve&amp;lt;ICoordinator&gt;().Coordinate();
    
    Console.WriteLine("Plugins...");

    ResolverEngine.ResolveAll&amp;lt;IPlugin&gt;().ForEach(p =&gt; p.DoSomething());             

    Console.WriteLine("Now registering this, and running plugins again...");

    ResolverEngine.RegisterAssembly(typeof(Program).Assembly);

    ResolverEngine.ResolveAll&amp;lt;IPlugin&gt;().ForEach(p =&gt; p.DoSomething());           

    Console.ReadLine();
}

&lt;/pre&gt;
&lt;p&gt;While it is fun to compile and run the application, the real power will come from stepping through in debug and watching the various steps of parsing out types and constructors. Looking at &lt;code&gt;ConstructorInfo&lt;/code&gt; and &lt;code&gt;ParameterInfo&lt;/code&gt; will reveal a lot about how C# interacts with the underlying CLR. Even if you never use this code, it will help you better understand and interact with the various dependency injection frameworks that are available and learn a little more about what they are doing for you behind the scenes. This only brushes the surface ... pulling down an open source project and wading through the code will reveal how much more powerful these frameworks are.
&lt;p&gt;&lt;a href="http://www.wintellect.com/CS/files/folders/sample_files/entry11579.aspx" target="_blank"&gt;Download the Source for this Example&lt;/a&gt;
&lt;p&gt;&lt;a href="http://jeremylikness.com/" title="Jeremy Likness"&gt;&lt;img border="0" src="http://jeremylikness.com/signature.gif" alt="Jeremy Likness" title="Jeremy Likness"/&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8944256652433533647-6557735635764111573?l=csharperimage.jeremylikness.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/CSharperImage?a=vL-GOkMevHQ:C9gaJ43HEpw:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CSharperImage?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/CSharperImage?a=vL-GOkMevHQ:C9gaJ43HEpw:YwkR-u9nhCs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CSharperImage?d=YwkR-u9nhCs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/CSharperImage?a=vL-GOkMevHQ:C9gaJ43HEpw:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CSharperImage?i=vL-GOkMevHQ:C9gaJ43HEpw:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/CSharperImage?a=vL-GOkMevHQ:C9gaJ43HEpw:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CSharperImage?i=vL-GOkMevHQ:C9gaJ43HEpw:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/CSharperImage?a=vL-GOkMevHQ:C9gaJ43HEpw:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CSharperImage?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/CSharperImage?a=vL-GOkMevHQ:C9gaJ43HEpw:I9og5sOYxJI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CSharperImage?d=I9og5sOYxJI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/CSharperImage/~4/vL-GOkMevHQ" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://csharperimage.jeremylikness.com/feeds/6557735635764111573/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://csharperimage.jeremylikness.com/2010/01/making-your-own-8k-homegrown-inversion.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8944256652433533647/posts/default/6557735635764111573?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8944256652433533647/posts/default/6557735635764111573?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/CSharperImage/~3/vL-GOkMevHQ/making-your-own-8k-homegrown-inversion.html" title="Making Your Own 8K Homegrown Inversion of Control Container" /><author><name>Jeremy Likness</name><uri>http://www.blogger.com/profile/18407945801671553594</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="05667915713066003387" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://csharperimage.jeremylikness.com/2010/01/making-your-own-8k-homegrown-inversion.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DkQGRHYyeCp7ImA9WxBQE08.&quot;"><id>tag:blogger.com,1999:blog-8944256652433533647.post-1363297361161404337</id><published>2010-01-12T14:13:00.003-05:00</published><updated>2010-01-12T14:25:25.890-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-01-12T14:25:25.890-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="schema" /><category scheme="http://www.blogger.com/atom/ns#" term="xml" /><category scheme="http://www.blogger.com/atom/ns#" term="embedded resources" /><title>Quick Tip: Embedding and Accessing Schemas in .NET</title><content type="html">&lt;p&gt;I have a project I'm working on that requires the use of some extensive XML manipulation. While XML can be very powerful, XML without a schema is like JavaScript objects: no strong typing and the wild west as far as standards are concerned. A good, solid XML document will have a valid schema to validate against.
&lt;p&gt;It's really not that difficult, either. There are several online tools that can help generate a template of the schema from a sample XML document, like &lt;a href="http://www.hitsw.com/xml_utilites/" target="_blank"&gt;this one&lt;/a&gt;. Visual Studio provides full intellisense for building out your schema.
&lt;p&gt;You can choose to actually publish the schema to a website for validation if it's an "open schema." If it's closed and you are simply using it for internal validation, then it makes sense to embed as a resource. 
&lt;p&gt;A best practice is to validate your method parameters before acting on them. In my methods that take in the XML document, I want to validate that it maps to the schema or throw an exception right away. 
&lt;p&gt;First, I'll add the schema to the project, then right-click and change it to an embedded resource. This ensures it is complied into the distributable binary.
&lt;p&gt;Next, I create a helper class to access the schema. I'm almost always going to want to validate it as a schema set, so instead of having to remember how to parse the manifest and get the resource stream each time, why not do it like this: 
&lt;pre class="brush: csharp;"&gt;

public static class SchemaAccess
{
    private const string SCHEMA = "MySchema.xsd";
    private const string SCHEMANAMESPACE = "http://mycompany.com/MySchema.xsd"; 

    public static XmlSchemaSet GetSchemaSet()
    {
        // replace this fully qualified name with the schema file
        string schemaPath = typeof(SchemaAccess).FullName.Replace("SchemaAccess", SCHEMA);
        XmlSchemaSet schemas = new XmlSchemaSet();
        schemas.Add(SCHEMANAMESPACE, XmlReader.Create(typeof(SchemaAccess).Assembly.GetManifestResourceStream(schemaPath)));
        return schemas;
    }
}

&lt;/pre&gt;
&lt;p&gt;Instead of hard-coding the path to the schema, I make sure my helper class is at the same level. The embedded resources are always accessed by the full namespace followed by the file name, so I can simply take the fully qualified name of the current helper class and then replace the class name with the resource name. If my helper class is at "Foo.Bar" then it will be "Foo.Bar.SchemaAccess." The replace will turn that into "Foo.Bar.MySchema.xsd" which is what I need to access the schema. 
&lt;p&gt;Then, I simply add it to the set and return it. Of course, if I'm dealing with multiple schemas, I can add those, too. 
&lt;p&gt;With LINQ, it's very easy to validate a schema. Simply add &lt;code&gt;System.Xml.Schema&lt;/code&gt; to your usings, then validate your &lt;code&gt;XDocument&lt;/code&gt; like this, using the &lt;code&gt;Validate&lt;/code&gt; extension method. Here is a sample unit test that prints the errors to the debug console:
&lt;pre class="brush: csharp;"&gt;

XmlSchemaSet schemas = SchemaAccess.GetSchemaSet();
bool validationErrors = false;
myDoc.Validate(schemas, (o, e) =&gt;
    {
        validationErrors = true;
        Debug.Print(e.Message);
    });
Assert.IsFalse(validationErrors, "The xml was invalid. View the debug console for details."); 

&lt;/pre&gt;
&lt;p&gt;In production, I'll just throw the exception. That's it!
&lt;p&gt;&lt;a href="http://jeremylikness.com/" title="Jeremy Likness"&gt;&lt;img border="0" src="http://jeremylikness.com/signature.gif" alt="Jeremy Likness" title="Jeremy Likness"/&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8944256652433533647-1363297361161404337?l=csharperimage.jeremylikness.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/CSharperImage?a=c7yD2KCh4xQ:HmIbRx7t4HI:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CSharperImage?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/CSharperImage?a=c7yD2KCh4xQ:HmIbRx7t4HI:YwkR-u9nhCs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CSharperImage?d=YwkR-u9nhCs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/CSharperImage?a=c7yD2KCh4xQ:HmIbRx7t4HI:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CSharperImage?i=c7yD2KCh4xQ:HmIbRx7t4HI:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/CSharperImage?a=c7yD2KCh4xQ:HmIbRx7t4HI:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CSharperImage?i=c7yD2KCh4xQ:HmIbRx7t4HI:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/CSharperImage?a=c7yD2KCh4xQ:HmIbRx7t4HI:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CSharperImage?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/CSharperImage?a=c7yD2KCh4xQ:HmIbRx7t4HI:I9og5sOYxJI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CSharperImage?d=I9og5sOYxJI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/CSharperImage/~4/c7yD2KCh4xQ" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://csharperimage.jeremylikness.com/feeds/1363297361161404337/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://csharperimage.jeremylikness.com/2010/01/quick-tip-embedding-and-accessing.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8944256652433533647/posts/default/1363297361161404337?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8944256652433533647/posts/default/1363297361161404337?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/CSharperImage/~3/c7yD2KCh4xQ/quick-tip-embedding-and-accessing.html" title="Quick Tip: Embedding and Accessing Schemas in .NET" /><author><name>Jeremy Likness</name><uri>http://www.blogger.com/profile/18407945801671553594</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="05667915713066003387" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://csharperimage.jeremylikness.com/2010/01/quick-tip-embedding-and-accessing.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CEMGQX89fCp7ImA9WxBQEkw.&quot;"><id>tag:blogger.com,1999:blog-8944256652433533647.post-3768139499977069149</id><published>2010-01-11T07:00:00.001-05:00</published><updated>2010-01-11T07:20:20.164-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-01-11T07:20:20.164-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="composite application guidance" /><category scheme="http://www.blogger.com/atom/ns#" term="composite wpf" /><category scheme="http://www.blogger.com/atom/ns#" term="fluent interfaces" /><category scheme="http://www.blogger.com/atom/ns#" term="prism" /><title>Auto-Discoverable Views using Fluent PRISM in Silverlight</title><content type="html">&lt;p&gt;One reason a developer would use a technology like &lt;a href="http://mef.codeplex.com/" target="_blank" title="Managed Extensibility Framework (MEF)"&gt;MEF&lt;/a&gt; is to, as the name implies, make an application extensible through a process called discovery. Discovery is simply a method for locating classes, types, or other resources in an assembly. MEF uses the &lt;code&gt;Export&lt;/code&gt; tag to flag items for discovery, and the composition process then aggregates those items and provides them to the entities requesting them via the &lt;code&gt;Import&lt;/code&gt; tag. 
&lt;p&gt;&lt;a href="http://www.wintellect.com/CS/files/folders/sample_files/entry11467.aspx" title="Auto-Discovery of Views using Fluent PRISM" target="_blank"&gt;Download the source code for this example&lt;/a&gt;
&lt;p&gt;It occurred to me when working with PRISM and MEF (see the recap of my short series &lt;a href="http://csharperimage.jeremylikness.com/2010/01/prism-mef-and-mvvm-part-3-of-3-dynamic.html" title="PRISM, MEF, and MVVM" target="_blank"&gt;here&lt;/a&gt;) that some of this can be done through traditional means and I might be abusing the overhead of a framework if all I'm doing is something simple like marrying a view to a region. 
&lt;p&gt;Challenges with PRISM include both determining how views make it into regions and how to avoid magic strings and have strict type compliance when dealing with regions. This post will address one possible solution using custom attributes and some &lt;i&gt;fluent interfaces&lt;/i&gt;. 
&lt;p&gt;&lt;b&gt;Fluent Interfaces&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;Fluent interfaces simply refers to the practice of using the built-in support for an object-oriented language to create more "human-readable" code. It's really a topic in and of itself, but I felt it made sense to simplify some of the steps in this post and introduce some higher level concepts and examples along the way.
&lt;p&gt;There are several ways to provide fluent interfaces. One that is built-in to the C# language is simply using the &lt;code&gt;type initializer&lt;/code&gt; feature. Instead of this: 
&lt;pre class="brush: csharp;"&gt;

public class MyClass 
{
   public string Foo { get; set; }
   public string Bar { get; set; }

   public MyClass() 
   {
   }

   public MyClass(string foo, string bar) 
   {
       Foo = foo; 
       Bar = bar;
   } 
}

&lt;/pre&gt;
&lt;p&gt;Which results in code like this: 
&lt;pre class="brush: csharp;"&gt;

...
MyClass myClass = new MyClass(string1, string2); 
...

&lt;/pre&gt;
&lt;p&gt;Question: which string is foo, and which string is bar, based on the above snippet? Would you consider this to be more readable and "self-documenting"? 
&lt;pre class="brush: csharp;"&gt;

...
MyClass myClass = new MyClass { Foo = string1, Bar = string2 };
...

&lt;/pre&gt;
&lt;p&gt;It works for me! So let's do something simple in our PRISM project. If you've worked with PRISM, then you'll know the pattern of creating a Shell and then assinging it to the root visual in a Bootstrapper. The typical code looks like this in your &lt;code&gt;Bootstrapper&lt;/code&gt; class:
&lt;pre class="brush: csharp;"&gt;

protected override DependencyObject CreateShell()
{
   Shell shell = new Shell(); 
   Application.Current.RootVisual = shell;
   return shell; 
}

&lt;/pre&gt;
&lt;p&gt;That's nice, but wouldn't it also be nice if you could do something simple and readable, like this? Keep in mind we're not cutting down on generated code (and in fact, sometimes fluent interfaces may increase the amount of generated code, which is a consideration to keep in mind), but we're focused on the maintainability and readability of the source code.
&lt;pre class="brush: csharp;"&gt;

protected override DependencyObject CreateShell()
{
   return Container.Resolve&amp;lt;Shell&gt;().AsRootVisual();             
}

&lt;/pre&gt;
&lt;p&gt;In one line of code I'm asking the container to provide me with the shell (I do this as a common practice as opposed to creating a new instance so that any dependencies I may have in the shell will be resolved), then return it "as root visual." I think that is pretty readable, but how do we get there? 
&lt;p&gt;The answer in this case is using extension methods. In my "common" project I created a static class called &lt;code&gt;Fluent&lt;/code&gt; which contains my fluent interfaces (this is for the example only and would not scale in production ... you will want to segregate your interfaces into separate classes related to the modules they act upon). In this static class, I create the following &lt;i&gt;extension method&lt;/i&gt;:
&lt;pre class="brush: csharp;"&gt;

public static UserControl AsRootVisual(this UserControl control)
{
    Application.Current.RootVisual = control;
    return control;
}

&lt;/pre&gt;
&lt;p&gt;An extension method does a few things. By using the keyword &lt;code&gt;this&lt;/code&gt; on the parameter, it tells the compiler this method will extend the type. The semantics in the code look you are calling something on the &lt;code&gt;UserControl&lt;/code&gt;, but the compiler is really taking the user control, then calling the method on the static class and passing the instance in. It is common for the extension methods to return the same instance so they can be chained. In this case, we simply assign the control to the root visual, then return it so it can be used elsewhere. We're really doing the same thing we did before, but adding a second method call, in order to make the code that much more readable.
&lt;p&gt;One important concern to have and address with fluent interfaces is the potential for "hidden magic." What I mean by this is the extension methods aren't available on the base class and only appear when you include a reference to the class with the extensions. This may make them less discoverable based on how you manage your code. It also means you will look at methods that aren't part of the known interface. It's not difficult to determine where the method comes from. Intellisense will flag extension methods as extensions, and you can always right click and "go to definition" to see where the method was declared.
&lt;p&gt;&lt;b&gt;Auto-discoverable Views&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;I have two main goals with this project: the first is to be able to tag views so they are automatically discovered and placed into a region, and the second is to type the region so I'm not using magic strings all over the place. My ideal solution would allow me to add a view to a project, tag it with a region, and run it, and have it magically appear in that region. Possible? Of course!
&lt;p&gt;&lt;b&gt;Typing the Regions&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;I am going to type the regions to avoid magic strings. Because the main shell defines the regions, I'm fine with the strings there ... that is sort of the "overall definition", but then I want to make sure elsewhere in the code I can't accidentally refer to a region that doesn't exist. My first step is to create a common project that all other modules can reference, and then add an enumeration for the regions. The enumeration for this examle is simple:
&lt;pre class="brush: csharp;"&gt;

namespace ViewDiscovery.Common
{
   public enum Regions
    {
        TopLeft,
        TopRight,
        BottomLeft,
        BottomRight
    }
}

&lt;/pre&gt;
&lt;p&gt;Enumerations are nice because I can call &lt;code&gt;ToString()&lt;/code&gt; and turn it into the string value of the enumeration itself. I decided to adopt the convention "Region.&lt;region&gt;" when tagging it in the shell, so my shell looks like this:
&lt;pre class="brush: csharp;"&gt;

&amp;lt;UserControl x:Class="ViewDiscovery.Shell"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:region="clr-namespace:Microsoft.Practices.Composite.Presentation.Regions;assembly=Microsoft.Practices.Composite.Presentation"
    &gt;
    &amp;lt;Grid x:Name="LayoutRoot" Background="White"&gt;
        &amp;lt;Grid.RowDefinitions&gt;
            &amp;lt;RowDefinition Height="Auto"/&gt;
            &amp;lt;RowDefinition Height="Auto"/&gt;
            &amp;lt;RowDefinition Height="Auto"/&gt;
        &amp;lt;/Grid.RowDefinitions&gt;
        &amp;lt;Grid.ColumnDefinitions&gt;
            &amp;lt;ColumnDefinition Width="Auto"/&gt;
            &amp;lt;ColumnDefinition Width="Auto"/&gt;
        &amp;lt;/Grid.ColumnDefinitions&gt;
        &amp;lt;TextBlock Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="2" HorizontalAlignment="Center" Text="View Discovery"/&gt;       
        &amp;lt;ItemsControl Grid.Row="1" Grid.Column="0" region:RegionManager.RegionName="Region.TopLeft"/&gt;
        &amp;lt;ItemsControl Grid.Row="1" Grid.Column="1" region:RegionManager.RegionName="Region.TopRight"/&gt;
        &amp;lt;ItemsControl Grid.Row="2" Grid.Column="0" region:RegionManager.RegionName="Region.BottomLeft"/&gt;
        &amp;lt;ItemsControl Grid.Row="2" Grid.Column="1" region:RegionManager.RegionName="Region.BottomRight"/&gt;
    &amp;lt;/Grid&gt;
&amp;lt;/UserControl&gt;

&lt;/pre&gt;
&lt;p&gt;This is just a simple 2x2 grid with a region per cell. I used the &lt;code&gt;ItemsControl&lt;/code&gt; so each cell can host multiple views. We're off to a good start! Now let's figure out how to tag our views.
&lt;p&gt;&lt;b&gt;The Custom Attribute&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;Custom attributes are powerful and easy to implement. I want to be able to tag a view as a region using my enumeration, so I define this custom attribute:
&lt;pre class="brush: csharp;"&gt;

namespace ViewDiscovery.Common
{
    [AttributeUsage(AttributeTargets.Class,AllowMultiple=false)]
    public class RegionAttribute : System.Attribute
    {
        const string REGIONTEMPLATE = "Region.{0}";

        public readonly string Region;

        public RegionAttribute(Regions region)
        {
            Region = region.ToString().FormattedWith(REGIONTEMPLATE);              
        }
    }
}

&lt;/pre&gt;
&lt;p&gt;Notice that I don't allow multiple attributes and that this attribute is only valid when placed on a class. Attributes can take both &lt;i&gt;positional parameters&lt;/i&gt; (defined in the constructor) and &lt;i&gt;named parameters&lt;/i&gt; (defined as properties). In this case, I only have one value so I chose to make it positional. When the region enumeration is passed in, I cast it to a string and then format it with the prefix, so that &lt;code&gt;Regions.TopLeft&lt;/code&gt; becomes the string &lt;code&gt;Region.TopLeft&lt;/code&gt;. Notice I snuck in another fluent interface, the &lt;code&gt;FormattedWith&lt;/code&gt;. To me, that's a sight prettier than "string.Format" if I'm only dealing with a single parameter. The extension to make this happen looks like this:
&lt;pre class="brush: csharp;"&gt;

public static string FormattedWith(this string src, string template)
{
    return string.Format(template, src);
}

&lt;/pre&gt;
&lt;p&gt;Now that we have a tag, we can create a new module and get it wired in. I created a new project as a Silverlight Class Library (sorry, this example doesn't do any fancy dynamic module loading), built a folder for views, and tossed in a view. The view simply contains a grid with some text:
&lt;pre class="brush: xml;"&gt;

&amp;lt;Grid x:Name="LayoutRoot" Background="White"&gt;
        &amp;lt;Grid.RowDefinitions&gt;
            &amp;lt;RowDefinition/&gt;
            &amp;lt;RowDefinition/&gt;
        &amp;lt;/Grid.RowDefinitions&gt;
        &amp;lt;TextBlock Text="I am in ModuleOne." Grid.Row="0"/&gt;
        &amp;lt;TextBlock Text="I want to be at the top left." Grid.Row="1"/&gt;
    &amp;lt;/Grid&gt;

&lt;/pre&gt;
&lt;p&gt;Tagging the view was simple. I went into the code-behind, added a &lt;code&gt;using&lt;/code&gt; statement to reference the common project where my custom attribute is defined and then tagged the view with the attribute. Here's the code-behind with the tag:
&lt;pre class="brush: csharp;"&gt;

namespace ViewDiscovery.ModuleOne.Views
{
    [Region(Regions.TopLeft)] 
    public partial class View : UserControl
    {
        public View()
        {
            InitializeComponent();
        }       
    }
}

&lt;/pre&gt;
&lt;p&gt;So now it's clear where we want the view to go. Now how do we get it there?
&lt;p&gt;&lt;b&gt;Discovering the Views&lt;/b&gt;
&lt;p&gt;The pattern in PRISM for injecting a module is for the module to have an initialization class that implements &lt;code&gt;IModule&lt;/code&gt; and then adds the views in the module to the region. We want to do this through discovery. To facilitate this, I created a base abstract class for any module that wants auto-discovered views. The class looks like this:
&lt;pre class="brush: csharp;"&gt;

public abstract class ViewModuleBase : IModule
{
    protected IRegionManager _regionManager;

    public ViewModuleBase(IRegionManager regionManager)
    {
        _regionManager = regionManager;
    }

    #region IModule Members

    public virtual void Initialize()
    {
        IEnumerable&amp;lt;Type&gt; views = GetType().Assembly.GetTypes().Where(t =&gt; t.HasRegionAttribute());

        foreach (Type view in views)
        {
            RegionAttribute regionAttr = view.GetRegionAttribute(); 
            _regionManager.RegisterViewWithRegion(regionAttr.Region, view); 
        }
    }

    #endregion
}

&lt;/pre&gt;
&lt;p&gt;The code should be very readable. We enforce that the region manager must be passed in by creating a constructor that takes it and stores it. We implement &lt;code&gt;Initialize&lt;/code&gt; as virtual so it can be overridden when needed. First, we get the assembly the module lives in, then grab a collection of types that have our custom attribute. Yes, our fluent interface makes this obvious because we can do &lt;code&gt;type.HasRegionAttribute()&lt;/code&gt;. The extension method looks like this:
&lt;pre class="brush: csharp;"&gt;

public static bool HasRegionAttribute(this Type t)
{
    return t.GetCustomAttributes(true).Where(a =&gt; a is RegionAttribute).Count() &gt; 0; 
}

&lt;/pre&gt;
&lt;p&gt;This takes the type, grabs the collection of custom attributes (using inheritance in case we're dealing with a derived type) and returns true if the count of our attribute, the &lt;code&gt;RegionAttribute&lt;/code&gt;, is greater than zero. 
&lt;p&gt;Next, we iterate those types and get the region attribute, again with a nice, friendly interface (&lt;code&gt;GetRegionAttribute&lt;/code&gt;) that looks like this:
&lt;pre class="brush: csharp;"&gt;

public static RegionAttribute GetRegionAttribute(this Type t)
{
    return (RegionAttribute)t.GetCustomAttributes(true).Where(a =&gt; a is RegionAttribute).SingleOrDefault();
}

&lt;/pre&gt;
&lt;p&gt;Now we have exactly what we need to place the view into the region: the region it belongs to, and the type. So, we register the view with the region and we're good to go! 
&lt;p&gt;In my module, I add a class for the module initializer called &lt;code&gt;ModuleInit&lt;/code&gt;. I'm only using the auto-discovery so there is nothing more than an implementation of the base class that passes the region manager down: 
&lt;pre class="brush: csharp;"&gt;

namespace ViewDiscovery.ModuleOne
{
    public class ModuleInit : ViewModuleBase
    {
        public ModuleInit(IRegionManager regionManager)
            : base(regionManager)
        {
        }
    }
}

&lt;/pre&gt;
&lt;p&gt;Now we go back to the main project and wire in the module catalog. I'm not using dynamic modules so I just reference my modules from the main project and register them by type: 
&lt;pre class="brush: csharp;"&gt;

protected override IModuleCatalog GetModuleCatalog()
{
    return new ModuleCatalog()
        .WithModule(typeof(ModuleOne.ModuleInit).AssemblyQualifiedName.AsModuleWithName("Module One"));            
}      

&lt;/pre&gt;
&lt;p&gt;OK, so I had some fun here as well. I wanted to extend the module catalog to allow chaining &lt;code&gt;WithModule&lt;/code&gt; for adding multiple modules, and be able to take a type name as a string, then make it a module with a name. Working backwards, we turn a string into a named &lt;code&gt;ModuleInfo&lt;/code&gt; class like this:
&lt;pre class="brush: csharp;"&gt;

public static ModuleInfo AsModuleWithName(this string strType, string moduleName)
{
    return new ModuleInfo(moduleName, strType);
}

&lt;/pre&gt;
&lt;p&gt;Next, we extend the catalog to allow chaining on new modules like this:
&lt;pre class="brush: csharp;"&gt;

public static ModuleCatalog WithModule(this ModuleCatalog catalog, ModuleInfo module)
{
    catalog.AddModule(module);
    return catalog;
}

&lt;/pre&gt;
&lt;p&gt;Notice this simply adds the module then returns the original catalog. 
&lt;p&gt;At this point, we can run the project and see that the view appears in the upper left. 
&lt;p&gt;&lt;img src="http://gallery.jeremylikness.com/main.php?g2_view=core.DownloadItem&amp;g2_itemId=160&amp;g2_serialNumber=1" title="View Discovery with One View" alt="View Discovery with One View"/&gt;
&lt;p&gt;I then added a second view with a rectangle: 
&lt;pre class="brush: xml;"&gt;

&amp;lt;UserControl x:Class="ViewDiscovery.ModuleOne.Views.Rectangle"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    &gt;
    &amp;lt;Grid x:Name="LayoutRoot" Background="White"&gt;
        &amp;lt;Rectangle Width="100" Height="100" Fill="Red" Stroke="Black"/&gt;
    &amp;lt;/Grid&gt;
&amp;lt;/UserControl&gt;

&lt;/pre&gt;
&lt;p&gt;... and tagged it:
&lt;pre class="brush: csharp;"&gt;

namespace ViewDiscovery.ModuleOne.Views
{
    [Region(Regions.TopRight)] 
    public partial class Rectangle : UserControl
    {
        public Rectangle()
        {
            InitializeComponent();
        }
    }
}

&lt;/pre&gt;
&lt;p&gt;An finally compiled and re-ran it. The rectangle shows up in the upper right, as expected:
&lt;p&gt;&lt;img src="http://gallery.jeremylikness.com/main.php?g2_view=core.DownloadItem&amp;g2_itemId=162&amp;g2_serialNumber=1" title="View Discovery with Two Views" alt="View Discovery with Two Views"/&gt;
&lt;p&gt;Next, I added a second module with several views ... including a few registered to the same cell. Adding the new module to the catalog was easy with the extension for chaining modules:
&lt;pre class="brush: csharp;"&gt;

protected override IModuleCatalog GetModuleCatalog()
{
    return new ModuleCatalog()
        .WithModule(typeof(ModuleOne.ModuleInit).AssemblyQualifiedName.AsModuleWithName("Module One"))
        .WithModule(typeof(ModuleTwo.ModuleInit).AssemblyQualifiedName.AsModuleWithName("Module Two"));            
}   

&lt;/pre&gt;
&lt;p&gt;Compiling and running this gives me the final result: 
&lt;p&gt;&lt;img src="http://gallery.jeremylikness.com/main.php?g2_view=core.DownloadItem&amp;g2_itemId=164&amp;g2_serialNumber=1" alt="View Discovery with Multiple Views" title="View Discovery with Multiple Views"/&gt;
&lt;p&gt;And now we've successfully created auto-discoverable views that we can strongly type to a region and feel confident will end up being rendered where they belong.
&lt;p&gt;&lt;a href="http://www.wintellect.com/CS/files/folders/sample_files/entry11467.aspx" title="Auto-Discovery of Views using Fluent PRISM" target="_blank"&gt;Download the source code for this example&lt;/a&gt;
&lt;p&gt;&lt;a href="http://jeremylikness.com/" title="Jeremy Likness"&gt;&lt;img border="0" src="http://jeremylikness.com/signature.gif" alt="Jeremy Likness" title="Jeremy Likness"/&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8944256652433533647-3768139499977069149?l=csharperimage.jeremylikness.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/CSharperImage?a=x2TYFV6tBcM:f6F7savbUv8:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CSharperImage?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/CSharperImage?a=x2TYFV6tBcM:f6F7savbUv8:YwkR-u9nhCs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CSharperImage?d=YwkR-u9nhCs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/CSharperImage?a=x2TYFV6tBcM:f6F7savbUv8:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CSharperImage?i=x2TYFV6tBcM:f6F7savbUv8:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/CSharperImage?a=x2TYFV6tBcM:f6F7savbUv8:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CSharperImage?i=x2TYFV6tBcM:f6F7savbUv8:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/CSharperImage?a=x2TYFV6tBcM:f6F7savbUv8:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CSharperImage?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/CSharperImage?a=x2TYFV6tBcM:f6F7savbUv8:I9og5sOYxJI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CSharperImage?d=I9og5sOYxJI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/CSharperImage/~4/x2TYFV6tBcM" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://csharperimage.jeremylikness.com/feeds/3768139499977069149/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://csharperimage.jeremylikness.com/2010/01/auto-discoverable-views-using-fluent.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8944256652433533647/posts/default/3768139499977069149?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8944256652433533647/posts/default/3768139499977069149?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/CSharperImage/~3/x2TYFV6tBcM/auto-discoverable-views-using-fluent.html" title="Auto-Discoverable Views using Fluent PRISM in Silverlight" /><author><name>Jeremy Likness</name><uri>http://www.blogger.com/profile/18407945801671553594</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="05667915713066003387" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://csharperimage.jeremylikness.com/2010/01/auto-discoverable-views-using-fluent.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CUANRn8-cSp7ImA9WxBQEEg.&quot;"><id>tag:blogger.com,1999:blog-8944256652433533647.post-2399177367906616157</id><published>2010-01-09T01:00:00.000-05:00</published><updated>2010-01-09T11:16:37.159-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-01-09T11:16:37.159-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="automated testing" /><category scheme="http://www.blogger.com/atom/ns#" term="unit testing" /><category scheme="http://www.blogger.com/atom/ns#" term="silverlight" /><category scheme="http://www.blogger.com/atom/ns#" term="silverlight unit test" /><title>Automated Silverlight Unit Testing Using StatLight</title><content type="html">&lt;p&gt;One concern with the &lt;a href="http://code.msdn.microsoft.com/silverlightut" target="_blank" title="Silverlight Unit Testing Framework"&gt;Silverlight Unit Testing Framework&lt;/a&gt; is that it runs on a UI thread and requires a browser to function. This makes it difficult to integrate into automated or continuous integration testing. Difficult, but not impossible.
&lt;p&gt;A solution is provided by the project called &lt;a href="http://statlight.codeplex.com/" target="_blank" title="StatLight"&gt;StatLight&lt;/a&gt; which not only supports Silverlight testing automation, but actually integrates with several different unit test providers. I am focusing on the Silverlight UT for this post. The program is very flexible and will even run as an continuous test server by watching a XAP file for changes and triggering the tests when it does. It will output to the console and to an XML formatted file, making it easy to grab and process test results.
&lt;p&gt;I decided to run the tests I made in the &lt;a href="http://csharperimage.jeremylikness.com/2010/01/silverlight-unit-testing-framework.html" target="_blank"&gt;Unit Testing Asynchronous Behaviors in Silverlight&lt;/a&gt; post. First, I headed over to the StatLight web site and downloaded the project. I simply unzipped it into a folder to "install."
&lt;p&gt;Next, I copied the XAP file for my tests, called &lt;code&gt;PRISMMEF.Tests.xap&lt;/code&gt;, into the folder with StatLight (you can reference the full path, this was just for convenience). I created a subdirectory called reports. 
&lt;p&gt;I launched a command line as administrator. StatLight launches its own web service so elevated permissions are required to allow it to bind to the appropriate ports. At the command line, I ran the following. It started the test run, placed a dot on my screen for every test run, and then completed.
&lt;p&gt;&lt;img src="http://gallery.jeremylikness.com/main.php?g2_view=core.DownloadItem&amp;g2_itemId=158&amp;g2_serialNumber=2" title="Silverlight Unit Test Automation" alt="Silverlight Unit Test Automation"/&gt;
&lt;p&gt;This resulted in the following output as a file called &lt;code&gt;report.xml&lt;/code&gt;:
&lt;pre class="brush: xml;"&gt;
&amp;lt;StatLightTestResults xapFileName="PRISMMEF.Tests.xap" total="6" ignored="0" failed="0" dateRun="2010-01-08 19:15:18"&gt;
  &amp;lt;tests&gt;
    &amp;lt;test name="PRISMMEF.Tests.Common.PartModuleTest.TestConstructor" passed="True" timeToComplete="00:00:00.0290016" /&gt;
    &amp;lt;test name="PRISMMEF.Tests.Common.PartModuleTest.TestInitialization" passed="True" timeToComplete="00:00:00.1300074" /&gt;
    &amp;lt;test name="PRISMMEF.Tests.Common.ViewModelBehaviorTest.TestAttach" passed="True" timeToComplete="00:00:00.0340020" /&gt;
    &amp;lt;test name="PRISMMEF.Tests.Common.ViewModelBehaviorTest.TestFromXaml" passed="True" timeToComplete="00:00:00.1100063" /&gt;
    &amp;lt;test name="PRISMMEF.Tests.Common.ViewModelProviderTest.TestConstruction" passed="True" timeToComplete="00:00:00.0630036" /&gt;
    &amp;lt;test name="PRISMMEF.Tests.Common.ViewModelProviderTest.TestPropertyChange" passed="True" timeToComplete="00:00:00.0520030" /&gt;
  &amp;lt;/tests&gt;
&amp;lt;/StatLightTestResults&gt;
&lt;/pre&gt;
&lt;p&gt;From this, you can quickly see what I do with my Friday evenings. Seriously, it's a nice, simply, easy to iterate XML format that I can plug into my build scripts, parse with a program or even use simple XSLT and generate nice automated reports for the results of testing and even fail a build based on failed results.
&lt;p&gt;&lt;a href="http://jeremylikness.com/" title="Jeremy Likness"&gt;&lt;img border="0" src="http://jeremylikness.com/signature.gif" alt="Jeremy Likness" title="Jeremy Likness"/&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8944256652433533647-2399177367906616157?l=csharperimage.jeremylikness.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/CSharperImage?a=ZhwEdyMiuCw:wOkyZnmY_w8:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CSharperImage?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/CSharperImage?a=ZhwEdyMiuCw:wOkyZnmY_w8:YwkR-u9nhCs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CSharperImage?d=YwkR-u9nhCs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/CSharperImage?a=ZhwEdyMiuCw:wOkyZnmY_w8:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CSharperImage?i=ZhwEdyMiuCw:wOkyZnmY_w8:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/CSharperImage?a=ZhwEdyMiuCw:wOkyZnmY_w8:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CSharperImage?i=ZhwEdyMiuCw:wOkyZnmY_w8:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/CSharperImage?a=ZhwEdyMiuCw:wOkyZnmY_w8:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CSharperImage?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/CSharperImage?a=ZhwEdyMiuCw:wOkyZnmY_w8:I9og5sOYxJI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CSharperImage?d=I9og5sOYxJI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/CSharperImage/~4/ZhwEdyMiuCw" height="1" width="1"/&gt;</content><link rel="related" href="http://statlight.codeplex.com/" title="Automated Silverlight Unit Testing Using StatLight" /><link rel="replies" type="application/atom+xml" href="http://csharperimage.jeremylikness.com/feeds/2399177367906616157/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://csharperimage.jeremylikness.com/2010/01/automated-silverlight-unit-testing.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8944256652433533647/posts/default/2399177367906616157?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8944256652433533647/posts/default/2399177367906616157?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/CSharperImage/~3/ZhwEdyMiuCw/automated-silverlight-unit-testing.html" title="Automated Silverlight Unit Testing Using StatLight" /><author><name>Jeremy Likness</name><uri>http://www.blogger.com/profile/18407945801671553594</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="05667915713066003387" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://csharperimage.jeremylikness.com/2010/01/automated-silverlight-unit-testing.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CEMGSXo6eSp7ImA9WxBRGEQ.&quot;"><id>tag:blogger.com,1999:blog-8944256652433533647.post-306119620667526132</id><published>2010-01-07T14:25:00.000-05:00</published><updated>2010-01-07T14:27:08.411-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-01-07T14:27:08.411-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="silverlight toolkit" /><category scheme="http://www.blogger.com/atom/ns#" term="unit testing" /><category scheme="http://www.blogger.com/atom/ns#" term="silverlight unit test" /><title>Silverlight Unit Testing Framework: Asynchronous Testing of Behaviors</title><content type="html">&lt;p&gt;Last month, I bogged about &lt;a href="http://csharperimage.jeremylikness.com/2009/12/unit-tests-for-viewmodels-and-views-in.html" target="_blank"&gt;Unit Testing ViewModels AND Views&lt;/a&gt; using the &lt;a href="http://code.msdn.microsoft.com/silverlightut/" target="_blank" title="Silverlight Unit Testing Framework"&gt;Silverlight Unit Testing Framework&lt;/a&gt;. I wanted to take that post a step further and talk about some more advanced testing scenarios that are possible.
&lt;p&gt;The site itself provides a lot of information about how to get started and what is available with the framework. One thing to keep in mind that is a radical shift from other testing frameworks is that the Silverlight testing framework runs on the UI thread. This means it does not spawn multiple threads for multiple tests and in fact requires the tests to run "one at a time" so they can take advantage of the test surface that is supplied. 
&lt;p&gt;This is a bit different than other frameworks but in my opinion, makes a lot of sense when dealing with Silverlight. The framework provides incredible flexibility for configuring and categorizing your tests. 
&lt;p&gt;If you are searching for a very comprehensive example of the framework in use, look no further than the &lt;a href="http://www.codeplex.com/Silverlight" target="_blank"&gt;Silverlight Toolkit&lt;/a&gt;. This comes with all source code and in fact uses the testing framework for its tests. You will find not only advanced scenarios for testing, but thousands upon thousands of tests! (I also am guessing that a new standard for PC performance has been invented by mistake ... let's all compile the entire toolkit and compare how long it takes!) 
&lt;p&gt;&lt;b&gt;Tagging Tests&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;One thing you'll find if you run the toolkit tests is that you can enter a tag to filter tests. For example, type in "Accordion" to only run the 800 or so unit tests for accordion-type controls. 
&lt;p&gt;To use tag functionality, simply "tag" your test like this: 
&lt;pre class="brush: csharp;"&gt;

[TestClass] 
[Tag("MEF")]
public class PartModuleTest 
{
}

&lt;/pre&gt;
&lt;p&gt;I've tagged the test to be a MEF-related test. When I wire up the framework, I can filter the tag like this:
&lt;pre class="brush: csharp;"&gt;

UnitTestSettings settings = UnitTestSystem.CreateDefaultSettings();
settings.TagExpression = "MEF";
this.RootVisual = UnitTestSystem.CreateTestPage(settings);  

&lt;/pre&gt;
&lt;p&gt;When I run the tests, only my tests tagged with MEF will run! The toolkit provides an example of a UI that allows you to select the tag, then run the test.
&lt;p&gt;&lt;b&gt;Asynchronous Tests&lt;/b&gt;&lt;/p&gt; 
&lt;p&gt;It is often necessary to test methods that are asynchronous or require event coordination. An example may be a service that must wait on return values, or a user control that must be loaded into the framework before you can test it. The Silverlight Unit Testing Framework provides the &lt;code&gt;Asynchronous&lt;/code&gt; tag to facilitate this type of test. This tells the framework not to move onto the next test nor consider the current test method complete until an explicit call to &lt;code&gt;TestComplete&lt;/code&gt; is made.  
&lt;p&gt;There are several "helper" methods supplied for asynchronous processing that we'll explore in a minute. To use these methods requires inheriting from one of the base test classes such as &lt;code&gt;SilverlightTest&lt;/code&gt; which provides the methods as well as the test surface to add controls to. 
&lt;p&gt;In &lt;a href="http://csharperimage.jeremylikness.com/2009/12/prism-mef-and-mvvm-part-1-of-3-unity.html" title="PRISM, MEF, and MVVM: Unity Glue" target="_blank"&gt;PRISM, MEF, and MVVM Part 1 of 3: Unity Glue&lt;/a&gt; I explored various options for binding the view model to the view. The 3rd and final method I reviewed was using an attached behavior. I would like to write some unit tests for that behavior (indeed, if I were a test-driven development or TDD purist, I would have written those tests first). 
&lt;p&gt;In order to test the behavior, I need to attach it to a &lt;code&gt;FrameworkElement&lt;/code&gt; and then validate it has done what I expected it to do. But how do I go about doing that in our unit test environment? 
&lt;p&gt;&lt;b&gt;Attached Behaviors&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;Similar to other controls in other frameworks, Silverlight controls have a distinct life cycle. It varies slightly depending on whether the control has been generated in XAML or through code. There is a great summary table of these events on &lt;a href="http://blogs.msdn.com/devdave/archive/2008/10/11/control-lifecycle.aspx" target="_blank"&gt;Dave's Blog&lt;/a&gt;. What's important to note is that values and properties are set as soon as you, well, set them, but bindings don't take effect until they are inserted into the visual tree. In XAML, the XAML node becomes part of the tree and fires the &lt;code&gt;Loaded&lt;/code&gt; event once it is fully integrated. In code, this happens after the element is added as the child of some other element that is in the tree. This allows Silverlight to parse the hierarchy and propagate dependency properties. 
&lt;p&gt;So what we essentially want to do is take our behavior, attach it to an element, and then wait for the &lt;code&gt;Loaded&lt;/code&gt; event to fire so we can inspect the element and see that it has been modified accordingly (in this case, we expect that the &lt;code&gt;DataContext&lt;/code&gt; property has been set to our view model). 
&lt;p&gt;&lt;b&gt;Setting up the Project&lt;/b&gt;
&lt;p&gt;The testing framework provides some handy templates for getting started. I add a new project and select the Silverlight Test Project template. I then add references to the projects I'll be testing and the supporting frameworks like PRISM and MEF.
&lt;p&gt;Next, I'll want to build some helper classes to help me test my functionality.
&lt;p&gt;&lt;b&gt;Helper Classes&lt;/b&gt;
&lt;p&gt;I like to create a folder called &lt;code&gt;Helper&lt;/code&gt; and place my stubs, mocks, and other helper classes there. These may be utilities, like the &lt;a href="http://csharperimage.jeremylikness.com/2009/08/exception-expected-asserttrue.html" target="_blank"&gt;Exception Expected&lt;/a&gt; utility I use, or classes that are used for the testing framework.
&lt;p&gt;First, I'll create a test view model with a simple string and string collection property for testing:
&lt;pre class="brush: csharp;"&gt;

public class TestViewModel 
{
    public TestViewModel()
    {
        ListOfItems = new List&amp;lt;string&gt;();
    }

    public TestViewModel(List&amp;lt;string&gt; items)
    {
        ListOfItems = items;            
    }

    public string Property { get; set; }

    public List&amp;lt;string&gt; ListOfItems { get; set; }
}

&lt;/pre&gt;
&lt;p&gt;If my view models have common methods described in a base class or interface, I might use a mocking framework to mock the class instead. 
&lt;p&gt;&lt;b&gt;The Test Class&lt;/b&gt;
&lt;p&gt;The behavior I created has an affinity to the Unity inversion of control (IoC) container. It could be refactored otherwise, but it made sense for the sake of the demonstration. Therefore, I'll need to have a container for testing, as well as the view model. My test class starts out looking like this (notice I base it on &lt;code&gt;SilverlightTest&lt;/code&gt;): 
&lt;pre class="brush: csharp;"&gt;

[TestClass]
public class ViewModelBehaviorTest : SilverlightTest
{
    const string TESTPROP = "Test Property";

    IUnityContainer _container;

    TestViewModel _viewModel; 

    [ClassInitialize]
    public void ClassInitialize()
    {
        _container = new UnityContainer();

        _viewModel = new TestViewModel() { Property = TESTPROP }; 
        _container.RegisterInstance&amp;lt;TestViewModel&gt;(_viewModel); 

        ViewModelBehavior.Container = _container; 
    }
}

&lt;/pre&gt;
&lt;p&gt;I create a reference to the entire test class for the container and the test view model. When the class is initialized (this is one-time setup, before all tests are run) I create a container, a view model, and tell the container that anytime someone asks for the view model, give them the specific instance I created. I also set the container on the type for the view model behavior class, so it knows what to use when resolving the view model. 
&lt;p&gt;&lt;b&gt;The Code Behind Test&lt;/b&gt;
&lt;p&gt;For my first test, I'll programmatically attach the behavior and test that it works. The view model behavior takes in a string that is the fully qualified type name for the view model, and then uses the unity container to resolve it. Therefore, my test looks like this: 
&lt;pre class="brush: csharp;"&gt;

[TestMethod]
[Asynchronous]
[Description("Test creating an element and attaching in code behind.")]
public void TestAttach()
{
    TextBlock textBlock = new TextBlock();
    textBlock.SetValue(ViewModelBehavior.ViewModelProperty, typeof(TestViewModel).AssemblyQualifiedName);
                
    textBlock.Loaded += (o, e) =&gt; 
    {
        Assert.IsNotNull(textBlock.DataContext, "The data context was never bound.");
        Assert.AreSame(textBlock.DataContext, _viewModel, "The data context was not bound to the correct view model.");

        EnqueueTestComplete();
    };

    TestPanel.Children.Add(textBlock);                                  
}

&lt;/pre&gt;
&lt;p&gt;There's a few things going on here, so let's break them down! 
&lt;p&gt;The &lt;code&gt;TestMethod&lt;/code&gt; attribute tags this method to be run by the framework. It is decorated with a description, which I can view on the output when the test is run and helps make the test more, ah, descriptive. The first thing I do is create a test block and attach the view model property. Here, I'm taking the test view model and getting the fully qualified name and using that to set the attached property. We want to make sure everything works fine and there are no errors during binding, so this is where the asynchronous pieces come into play. 
&lt;p&gt;The &lt;code&gt;Asynchronous&lt;/code&gt; tag tells the framework that we're waiting on events, so don't consider this test complete until we explicitly tell the framework it's complete. When the text block fires the &lt;code&gt;Loaded&lt;/code&gt; event, we confirm that the data context is not null and that it in fact contains the exact instance of the view model we created in the class initialization. Then we tell the framework the test is complete by calling &lt;code&gt;EnqueueTestComplete&lt;/code&gt;, which is provided by the base class. 
&lt;p&gt;Finally, if you were to run this without the last line, the test would stall because the text block would never get loaded. We add it as a child of the test surface, and this injects it into the visual tree and fires the loaded event. 
&lt;p&gt;&lt;b&gt;The XAML Test&lt;/b&gt;
&lt;p&gt;I'm not completely confident with this test because the whole reason for creating a behavior was so I could attach the view model in XAML and not use code behind. Therefore, I should really test attaching this behavior through XAML. So, at the top of the test class we'll create the necessary XAML and wrap it in a &lt;code&gt;UserControl&lt;/code&gt;: 
&lt;pre class="brush: csharp;"&gt;

const string TESTXAML = 
    "&amp;lt;UserControl " +
        "xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\" "  +
        "xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\" " +
        "xmlns:vm=\"clr-namespace:PRISMMEF.Common.Behavior;assembly=PRISMMEF.Common\"&gt;" +
            "&amp;lt;Grid x:Name=\"LayoutRoot\" Background=\"White\" " +
                "vm:ViewModelBehavior.ViewModel=\"PRISMMEF.Tests.Helper.TestViewModel, PRISMMEF.Tests, Version=1.0.0.0\"&gt;" +
                "&amp;lt;ListBox x:Name=\"ListBox\" ItemsSource=\"{Binding ListOfItems}\"/&gt;" +
    "&amp;lt;/Grid&gt;&amp;lt;/UserControl&gt;";

&lt;/pre&gt;
&lt;p&gt;If you think the constant is ugly, you can always add an actual XAML file, set it as an embedded resource, then read it in instead. That would give you the full functionality of the editor to tweak the test code. Here, we simply create a control with a grid and a list box. The list box uses the attached behavior and also binds the list.
&lt;p&gt;I want to test the list binding as well, so I add a collection to my test class:
&lt;pre class="brush: csharp;"&gt;

.
private static readonly List&amp;lt;string&gt; _testCollection = new List&amp;lt;string&gt; { "test1", "test2" };         
.

&lt;/pre&gt;
&lt;p&gt;In the class initialize method, I'll pass this into the view model's constructor so it is set on the &lt;code&gt;ListOfItems&lt;/code&gt; property. 
&lt;p&gt;Now, we can create the control from XAML, load it, and test it: 
&lt;pre class="brush: csharp;"&gt;

[TestMethod]
[Asynchronous]
[Description("Test creating from XAML")]
public void TestFromXaml()
{
    UserControl control = XamlReader.Load(TESTXAML) as UserControl;
    
    control.Loaded += (o, e) =&gt; 
    {
        ListBox listBox = control.FindName("ListBox") as ListBox;

        Assert.IsNotNull(listBox, "ListBox was not found.");
        Assert.IsNotNull(listBox.DataContext, "The data context was never bound.");
        Assert.AreSame(listBox.DataContext, _viewModel, "The data context was not bound to the correct view model.");

        IEnumerable&amp;lt;string&gt; list = listBox.ItemsSource as IEnumerable&amp;lt;string&gt;; 
        List&amp;lt;string&gt; targetList = new List&amp;lt;string&gt;(list); 
        CollectionAssert.AreEquivalent(targetList, _testCollection, "Collection not properly bound."); 

        EnqueueTestComplete(); 
    };

    TestPanel.Children.Add(control);           
 }
&lt;/pre&gt; 
&lt;p&gt;Now we load the control from XAML and wire in the &lt;code&gt;Loaded&lt;/code&gt; event to test for the data context and the instance. Then, I take the items from the list box itself and compare them with the original list using &lt;code&gt;CollectionAssert&lt;/code&gt;. The &lt;code&gt;AreEquivalent&lt;/code&gt; does a set comparison. Then we signal the test is complete.
&lt;p&gt;There's no code for this example because it was very straightforward and I'll likely be posting a more comprehensive example in the future as the result of a talk I'll be giving. Be sure to tune into &lt;a href="http://blogs.msdn.com/geekspeak/" target="_blank"&gt;MSDN's geekSpeak&lt;/a&gt; on Wednesday, February 17th, 2010 when I will be the guest to cover exclusively the topic of the Silverlight Unit Testing Framework (the talks are all stored on the site in case you read this after the event).
&lt;p&gt;Thanks!
&lt;p&gt;&lt;a href="http://jeremylikness.com/" title="Jeremy Likness"&gt;&lt;img border="0" src="http://jeremylikness.com/signature.gif" alt="Jeremy Likness" title="Jeremy Likness"/&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8944256652433533647-306119620667526132?l=csharperimage.jeremylikness.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/CSharperImage?a=6D9LHNn6v_c:RHpQnYy1UrU:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CSharperImage?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/CSharperImage?a=6D9LHNn6v_c:RHpQnYy1UrU:YwkR-u9nhCs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CSharperImage?d=YwkR-u9nhCs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/CSharperImage?a=6D9LHNn6v_c:RHpQnYy1UrU:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CSharperImage?i=6D9LHNn6v_c:RHpQnYy1UrU:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/CSharperImage?a=6D9LHNn6v_c:RHpQnYy1UrU:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CSharperImage?i=6D9LHNn6v_c:RHpQnYy1UrU:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/CSharperImage?a=6D9LHNn6v_c:RHpQnYy1UrU:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CSharperImage?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/CSharperImage?a=6D9LHNn6v_c:RHpQnYy1UrU:I9og5sOYxJI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CSharperImage?d=I9og5sOYxJI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/CSharperImage/~4/6D9LHNn6v_c" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://csharperimage.jeremylikness.com/feeds/306119620667526132/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://csharperimage.jeremylikness.com/2010/01/silverlight-unit-testing-framework.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8944256652433533647/posts/default/306119620667526132?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8944256652433533647/posts/default/306119620667526132?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/CSharperImage/~3/6D9LHNn6v_c/silverlight-unit-testing-framework.html" title="Silverlight Unit Testing Framework: Asynchronous Testing of Behaviors" /><author><name>Jeremy Likness</name><uri>http://www.blogger.com/profile/18407945801671553594</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="05667915713066003387" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://csharperimage.jeremylikness.com/2010/01/silverlight-unit-testing-framework.html</feedburner:origLink></entry></feed>
