Understanding the decorator pattern.

Update (November 14th 2012): download a code sample that contains this hack.

The problem: You cannot bind to non-public types in LightSwitch.

So you’ve read the article about creating reusable modal screens in LightSwitch (whoa, thanks!), you tried it out (whoa, even more thanks!) and found out it only works in out-of-browser applications (whoa! bummer! My bad, sorry!!)

It took me a while to find some spare time (sorry about that), but I finally got around to digging into this exception (yes, I’m doing this over playing with the new HTML client :-)).   With the feedback from MikeH and Alfonso (thanks guys!), it was easy to diagnose the issue:

  • This works in an out-of-browser application.
  • This does not work in an “in-browser” application.  The stacktrace in the output window reveals:
System.Windows.Data Error: Cannot get ‘[Bla bla]’ value (type '[Bla bla]’) from ‘[more bla]’ (type ‘[something something]’). BindingExpression: Path=’[the path]’ DataItem=’[the data item] (HashCode=[whatever]); target element is ‘My imba user control’ (Name=”); target property is ‘[some prop]’ (type ‘[more fully qualified types in here]’).. System.MethodAccessException: Attempt by method ‘System.Windows.CLRPropertyListener.get_Value()’ to access method ‘[getter on the method]’ failed.
at System.RuntimeMethodHandle.PerformSecurityCheck(Object obj, RuntimeMethodHandleInternal method, RuntimeType parent, UInt32 invocationFlags)
at System.RuntimeMethodHandle.PerformSecurityCheck(Object obj, IRuntimeMethodInfo method, RuntimeType parent, UInt32 invocationFlags)
[more stacktrace here]
at System.Windows.PropertyAccessPathStep.ConnectToPropertyInSource(Boolean isSourceCollectionViewCurrentItem).

I’m including this stack trace so the next guy that runs into this problem can find this post.

Right, so back to analyzing the problem:  Bugger.  However, this behavior and stack trace seem to indicate there was a problem with the reflection being used in Silverlight bindings, which in turn is more restrictive in “in-browser” applications than it is in out-of-browser applications.  Indeed, with a bit of time spent on Bing, it turns out you cannot bind to properties on non-public types in Silverlight.  Even if these properties are exposed via a public interfaces.

Possible workarounds are:

  • Make your properties / classes public.  Say bye-bye to any good coding practices*sigh*.
  • Expose your privates.Well except for the fact this is the first time I explicitly write about my readers privates, I cannot make the internal types public since I do not own the assembly.   I mailed Microsoft to add ‘Application1337″, my test application, a trusted assembly from Microsoft.LightSwitch.Client.Internal.dll, the assembly that contains the internal type, but they politely refused.
  • Create a public decorator.

Understanding the decorator design pattern.

You can read all about the decorator pattern on wiki, or read my really short version here:

The decorator pattern is where you wrap one class around another.  The wrapper (the outer class) implements the same interface as the decorated class (the inner class), so the caller has no idea that there is a wrapper.  The wrapper delegates all calls to events, properties or methods, as defined on the interface, to the decorated class, except for those where the decorator chooses to alter the behavior.

Basically, if it looks like a duck, quacks like a duck and walks like a duck, it could be you’re dealing with a duck.  However, you aren’t sure.  If you ask it to Quack() (IDuck interface), it could be the Duck implementation (decorated class) that quacks, or it could be the farmer (wrapper, aka the decorator) that squeezes a duck hard enough to quack.  Some decorator classes are hard-coded, although you can create generic (dynamic proxy) implementations as well.

In our case, we had a problem binding to a non-public type.  We can create a decorator for our non-public type, which alters the behavior only by being a public type.

The code sample.

Here’s the decorator for the IScreenView, copy&paste the class to your LightSwitch project if you intend to make the reusable modal screens article work in in-browser applications:

    public class PresentationScreenViewDecorator : IScreenView
    {
        private IScreenView decorated;
        public PresentationScreenViewDecorator(IScreenView decorated)
        {
            this.decorated = decorated;
        }
        public void ActivateUIElement(Microsoft.LightSwitch.IBusinessObject target, Microsoft.LightSwitch.Details.IBusinessProperty targetProperty)
        {
            this.decorated.ActivateUIElement(target, targetProperty);
        }

        public void BeginModal(IScreenModalDialog dialog)
        {
            this.decorated.BeginModal(dialog);
        }

        public void CommitUIChanges()
        {
            this.decorated.CommitUIChanges();
        }

        public void EndModal(IScreenModalDialog dialog)
        {
            this.decorated.EndModal(dialog);
        }

        public bool Focus()
        {
            return this.decorated.Focus();
        }

        public IScreenModalDialog[] GetActiveModalDialogs()
        {
            return this.decorated.GetActiveModalDialogs();
        }

        public bool IsShowingModal
        {
            get { return this.decorated.IsShowingModal; }
        }

        public event System.EventHandler PreviewShowingModal
        {
            add
            {
                this.decorated.PreviewShowingModal += value;
            }
            remove
            {
                this.decorated.PreviewShowingModal -= value;
            }
        }

        public System.Windows.FrameworkElement RootUI
        {
            get { return this.decorated.RootUI; }
        }

        public IScreenObject Screen
        {
            get { return this.decorated.Screen; }
        }

        public IEnumerable ShellCommands
        {
            get { return this.decorated.ShellCommands; }
        }

        public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged
        {
            add
            {
                this.decorated.PropertyChanged += value;
            }
            remove
            {
                this.decorated.PropertyChanged -= value;
            }
        }

        public void Dispose()
        {
            this.decorated.Dispose();
            this.decorated = null;
        }
    }

A novice reader should be able to understand how this example works: I’m decorating an instance of IScreenView by delegating all calls on the IScreenView interface to properties, methods and events to the decorated instance.

A professional reader could notice I haven’t successfully succeeded in my encapsulation,  I should for example encapsulate the IShellCommands returned by the call to the ShellCommands property.  Make me.

Anyways, using this simple trick, you can now update the example from the Reusable Screens article like below:

        public MyModalWindow(ModalCall call)
        {

            this.call = call;

            //this.DataContext = this.call.ModalChildView;
            //Find the line above, and replace with:
            this.DataContext = new PresentationScreenViewDecorator(this.call.ModalChildView);

            InitializeComponent();

            this.Closing += MyModalWindow_Closing;

        }

Enjoy, and keep rocking LS!

PS: (insider) Yes, Michael Washington was right and I promise never to do that again. :-)

PS2: I created a bug about this.  Doesn’t seem like a logical equation… public interface + public property = binding should work.  

About these ads

15 thoughts on “Understanding the decorator pattern.

  1. Pingback: Creating reusable modal screens « Jan Van der Haegen's blog

  2. Hi Jan
    Thanks for the new code.

    Just a note: when I’m trying it, i have to change a little thing:

    public event System.EventHandler PreviewShowingModal
    {
    add
    {
    this.decorated.PreviewShowingModal += value;
    }
    remove
    {
    this.decorated.PreviewShowingModal -= value;
    }
    }

    TO:

    public event System.EventHandler PreviewShowingModal
    {
    add
    {
    this.decorated.PreviewShowingModal += value;
    }
    remove
    {
    this.decorated.PreviewShowingModal -= value;
    }
    }

    and I have to add this to implement the IScreenView interface

    event System.EventHandler IScreenView.PreviewShowingModal
    {
    add { throw new System.NotImplementedException(); }
    remove { throw new System.NotImplementedException(); }
    }

    IEnumerable IScreenView.ShellCommands
    {
    get { throw new System.NotImplementedException(); }
    }

    It works perfectly!
    Thanks so much

  3. Pingback: Windows Azure and Cloud Computing Posts for 8/2/2012+ - Windows Azure Blog

  4. Hi Jan,

    This is great post but I have a issue which I need help on it. When I try to close the window I keep getting error at call.ModalHostView.Dispatcher.BeginInvoke(

    Error: It is not valid to access this object on the current thread.

    Any idea what I may doing wrong.

    Ramin

    public static void CloseModalWindow(ModalCall call, bool closeHostView)
    {

    if (call != null && calls.Remove(call))
    {

    call.CallerView.EndModal(call.ModalHostView);

    if (closeHostView)

    call.ModalHostView.Dispatcher.BeginInvoke(

    () =>

    call.ModalHostView.Close()

    );

    }

    }

    • I fixed this by moving the whole routing inside the BeginInvoke (this is in VB.NET, but I’m sure you can translate):

      Public Shared Sub CloseModalWindow(mcall As ModalCall, closeHostView As Boolean)
      mcall.ModalHostView.Dispatcher.BeginInvoke(
      Sub()
      If mcall IsNot Nothing AndAlso calls.Remove(mcall) Then
      mcall.CallerView.EndModal(mcall.ModalHostView)
      If closeHostView Then
      mcall.ModalHostView.Close()
      End If
      End If
      End Sub)
      End Sub

  5. DESKTOP games or computer games have greater in
    popularity right now, not simply using the younger technology, but in addition
    with older people also. There are various online games available,
    beginning with the perceptive for the ordinary – your options are absolutely endless.

    On the internet role-playing games usually are one of the most a fact
    games throughout the complete world. With this particular popularity, a lot of men and women are researching and also striving to learn approaches
    to have the entire game as fast as they may;

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s