Wednesday, May 23, 2012

The Amazing EventProxy

Recently at work (as these posts usually come), I've been tasked with handling loading our entire framework (after downloading it from a remote source), and executing everything in a way that let's us administrate it.  I've been delving into the entire AppDomain paradigm which was plenty fun to deal with in the 70-536, but I haven't really touched it (or read on it) in about five years.

That being said, when working with AppDomain's, you have to make sure that the objects you're using can remote across to other AppDomain's correctly -- and by doing so, the easiest method is generally to derive the classes in the calls from MarshalByRefObject.  Pretty easy, huh?  Almost.

There is one caveat to this -- if you want to access an event on your cross-domain object, it requires your class to be Serializable or also be derived from MarshalByRefObject.  Still pretty simple, right?  Mostly -- but what if you have a control or user interface element that is already derived from something else?  Something that shouldn't be serialized at all...  In my case, it is a ViewModel.

After much deliberation, the smartest idea was to create a proxy -- pretty cool and easy, right?  Almost.  The only problem is that if I hard-coded the proxy, we'd be stuck with constantly updating the proxy for each and every object.  Some of our calls are just a simple EventHandler<EventArgs>, but some of our calls are more complicated EventHandler<MakesYourMindExplodeFromAnotherAppDomainEventArgs>.  How could I possibly allow this level of flexibility...?

Enter, the EventProxy:

    public class EventProxy<T, Args> : MarshalByRefObject
        where Args : EventArgs
    {
        public event EventHandler<Args> EventOccurred;

        public EventProxy(T instance, string eventName)
        {
            EventInfo eventOccurred = typeof(T).GetEvent(eventName);
            if (eventOccurred != null)
            {
                MethodInfo onEventOccurred = this.GetType().GetMethod("OnEventOccurred", BindingFlags.NonPublic | BindingFlags.Instance);

                Delegate handler = Delegate.CreateDelegate(eventOccurred.EventHandlerType, this, onEventOccurred);

                eventOccurred.AddEventHandler(instance, handler);
            }
        }

        private void OnEventOccurred(object sender, Args e)
        {
            if (EventOccurred != null)
                EventOccurred.Invoke(sender, e);
        }
    }

It is incredibly simple.

It's also important to note that this needs to be an assembly that both AppDomains reference.

For my ViewModel's, I'm adding it as such:

   EventProxy<CrossDomainObject, EventArgs<string>> Proxy = new EventProxy<CrossDomainObject, EventArgs<string>>(MyCrossDomainObject, "StatusUpdated");
   Proxy.EventOccurred += (sender, e) => { Status = e.Value };

In this example, CrossDomainObject is my CrossDomainObject class, wherein MyCrossDomainObject is the instance of that class.  The EventArgs<string> is a generic EventArgs that takes a string.  From there, I just update my status in the ViewModel, without any issues of the SerializationException.

There are a few safe-guards that would help make sure the EventProxy doesn't blow up and Exception out to hell, but it's a good start for someone to build on top of.

Thursday, May 17, 2012

DependencyProperty vs. INotifyPropertyChanged

I've been developing UI components for work and I've noticed a lot of shift and use between DependencyProperty and implementing the INotifyPropertyChanged interface.  When and why do we use this? 

The simplest answer is that DependencyProperty is a lot more heavyweight than INotifyPropertyChanged.  Primarily, you'll see DependencyProperty much more useful for UI components and binding, rather than on the ViewModel.  Why is this?

Simply put, implementing INotifyPropertyChanged will not allow you to style or template your control off the bat.  While there are other ways to get around this, it's a bit more of a pain and why make your life painful when you can make it simple and easy?

DependencyProperty, on the other hand, will allow you to do just that.  If you implement a Gauge control, for example, and then have it so that a specific element on the Gauge has a certain color, you won't be able to put a global style on this with INotifyPropertyChanged.  DependencyProperty will register it immediately and you're good to go.

I think it really boils down to two cases.

  1. For UI control development and tight-coupling, use DependencyProperty.
  2. For everything else (when serialization is necessary) use INotifyPropertyChanged.
That being said, there is one caveat -- writing the DependencyProperty in a ViewModel is a hell of a lot easier and quicker for updating things.  Using the "propdp" snippet in Visual Studio makes coding them a breeze.