Posts Tagged ‘ C# ’

Generalized Properties in C#

We’re all familiar with properties in C#.  Objects can have properties, property values can be got and set, and you can run code when they are got or set.  Simple, powerful, used all the time.

But they have a weakness.  Unless you get into the messy business of reflection, the compiler has to know at compile-time how you’re going to use the properties.  What do I mean by that?  I mean that to use a property on an object, you need to have a reference to that object, you need to know the type of that object, and your code needs to know both the name and type of the property.  The compiler needs to be able to resolve the whole usage.

Okay, but what if you need to make decisions about how to get or set properties at run-time?  Imagine you have a component that needs to do work on properties from a lot of different sources.  Let’s say it only knows the type of the properties and knows it needs to set them, but shouldn’t know about the parent objects or the real name of the properties?

What do we need?  Generalized properties!

Okay, so let’s distill a property down to it’s most basic form.  It has a value.  You can get that value.  You can set that value.  For simplicity’s sake and for now, let’s say we don’t even need to know the type of the value.  We’d like it to be easily portable.  BAM, let’s make it an object:

/// <summary>
    /// A PropertyProxy is an object that behaves like a property.  It has a Value that you can get or set.
    /// It can be databound to, allowing databinding decisions to be made at run-time.
    /// </summary>
    public abstract class PropertyProxy
    {
        public object Value
        {
            get
            {
                return this.getValue();
            }
            set
            {
                this.setValue(value);
            }
        }

        protected abstract object getValue();
        protected abstract void setValue(object value);
    }

This is the abstract base class.  In actual usage, we’d subclass it and provide a specific implementation for getValue and setValue.  Now we can instantiate one of these and pass it around, and client code doesn’t need to know about what’s actually happening when you get or set the value.

Other advantages:

– Complex databinding decisions can be made at run-time.

– It can be used to protect our data objects from meddling.  They have control over how they are used.

– We can run arbitrary code in getValue and setValue.  They don’t actually HAVE TO hook up to the getters and setters of real C# properties.  Imagine hooking setValue up to an Undo/Redo system.

Next time I’ll talk about how the PropertyProxy can be extended, and the real reason why we built it.  Why would we need to generalize properties?  I’ll let you sit with that.

Comparable WeakReferences in C#

C# provides us with a WeakReference object.  This object behaves like a normal reference, except that it does not prevent garbage collection of the target instance it refers to.  So if every other strong reference to an instance goes away or is nulled out, the .NET garbage collector will collect that instance, without regard to the weak references.  WeakReferences also provide an IsAlive property so you can check if the target still exists.

The WeakReference class has a weakness in certain situations that I’d like to address.  Let me start with an example.

Suppose you have two weak references and you want to know if they point to the same instance.  Something like this (very naive) example:

object instance1 = new object();

WeakReference ref1 = new WeakReference(instance1);
WeakReference ref2 = new WeakReference(instance1);

if (ref1 == ref2)
{
    // Do something
}

This will actually fail every time.  It’s comparing the references to the WeakReferences.  Because ref1 is a reference to a WeakReference instance, as is ref2.  What we really want is to compare the targets.  (Usually.)

So here I present the EquatableWeakReference class.  It behaves just like a WeakReference, but if you compare two of them, it compares the targets.

public class EquatableWeakReference
    {
        #region Private Members

        private int _targetHashCode;
        private WeakReference _weakReferenceToTarget;

        private void setTarget(object target)
        {
            _targetHashCode = target.GetHashCode();
            _weakReferenceToTarget = new WeakReference(target);
        }

        #endregion

        #region Public Interface

        public EquatableWeakReference(object target)
        {
            setTarget(target);
        }

        public object Target
        {
            get { return _weakReferenceToTarget.Target; }
            set
            {
                setTarget(value);
            }
        }

        public bool IsAlive
        {
            get
            {
                return _weakReferenceToTarget.IsAlive;
            }
        }

        public override int GetHashCode()
        {
            return _targetHashCode;
        }

        public override bool Equals(object obj)
        {
            return _targetHashCode == obj.GetHashCode();
        }

        #endregion
    }

As you can see, it has a similar constructor, and the same properties as the WeakReference.  It wraps the WeakReference, rather than inheriting from it, because we originally wrote this for use in Silverlight and you can’t inherit from WeakReference in Silverlight.

When you set the target, it records the target’s HashCode.  This is a unique* identifier of that object instance.  It uses those HashCodes to do comparisons.  It also overrides GetHashCode to return the target’s HashCode, rather than the EquatableWeakReference’s HashCode.  This also provides the advantage that if you use an EquatableWeakReference as a key in a Dictionary, it will be treated as the same key as a real reference to that object, because Dictionaries use the HashCode to index values.

(Which brings us to the whole reason for creating this.  We needed to make a WeakDictionary.  A Dictionary that would allow values to be garbage collected if the key instance was no longer alive.  This was a single-point fix to a widespread memory leak in an open-source library we were working with.  Oh, memory leaks… How you amuse me…)

 

* – It’s not really 100% unique, but it was good enough for our purposes.

Undo/Redo and Encapsulated Data Changes in Silverlight

We’re currently working on a Silverlight application that needed a robust undo/redo system.  Every change a user could make to data needed to be able to be undone.  At Affirma, we have a set of tools we’ve built for Silverlight – using an MVVM and Service-Oriented pattern – but this was not a tool already in it!  No matter, the great thing about a tool like an undo/redo system is that it must be a general tool, and so it could be added to our toolkit for use on many projects.

The way we chose to go about making this system was to abstract out the idea of a “Change”.  In the abstract, a change would be an encapsulated something (also known as a class, but the dramatic form is fun) that knew how to alter data both forwards and backwards.  Okay, that’s pretty abstract, so how about an example.  Let’s say we have a DeleteChange that can remove a piece of data from a repository.  This DeleteChange would need to know what piece of data it had to delete, it would need a way to delete that data, it would need to keep track of that data so the change could be undone, and it would need a way to add the data back for an undo.

Okay, some code:

namespace Affirma.Silverlight.Changes
{
    public abstract class Change
    {}

    /// <summary>
    /// A change does and undoes work on a target.
    /// </summary>
    public abstract class Change<TargetType> : Change
        where TargetType : class
    {
        /// <summary>
        /// An implementation should override this method and do work on the target here.
        /// </summary>
        public abstract void Do(TargetType target);

        /// <summary>
        /// An implementation should override this method and undo work on the target here.
        /// </summary>
        public abstract void Undo(TargetType target);

        /// <summary>
        /// An implementation should override this method and notify any listeners of the change here.
        /// </summary>
        public abstract void Notify(TargetType target);

        /// <summary>
        /// An implementation should override this method to finalize doing and undoing the action here.
        /// </summary>
        /// <param name="target"></param>
        public abstract void Finalize(TargetType target);
    }
}

A few notes:

1 – You would make a child class for each type of change you might want to make to your data.

2 – The changes are strongly typed (through generics) to the data object they will act upon.

3 – You implement methods for doing the change and undoing it.

4 – We added a Notify method.  In practice, often other systems would need to know about the change, so this is where you could notify them.

5 – We often found that we needed to “preview” a change, but not finalize it.  An example would be dragging an element around the screen.  We might need to “test the waters” of the change as we drag the element around, but we don’t want to finalize the change until we drop the element.  That’s why we have a finalize method.

6 – You’re probably getting the feeling about now that this system requires some discipline.  It does.  You MUST NOT alter data anywhere but inside a change.  However, we found that in practice, using that discipline up front saved us a lot of time down the road.  We always knew where to look to find where the data changed.  Data changes weren’t hiding in corners of the system.  And there was fantastic encapsulation.  Clients shouldn’t know what it takes to change the data.  They usually shouldn’t even know about all the data!  They just know they want a change, and these classes encapsulate it.

Okay, so the next step.  We wrote a service (internal to the Silverlight application) to manage these changes.  Here’s the interface:

namespace Affirma.Silverlight.Services
{
    /// <summary>
    /// An IChangeManagerService is used to manage data changes in systems where undo/redo
    /// functionality is desired. It is a generic interface, and the generic type is the type of
    /// the target that all the changes will act upon.  Generally, the target will be the root
    /// of a model graph.  The changes act upon this target to do their work, undo it, and redo it.
    /// </summary>
    /// <typeparam name="TargetType">The type of the target that all the changes will act upon.  Generally, the target will be the root of a model graph.</typeparam>
    public interface IChangeManagerService<TargetType> : IClientService
        where TargetType : class
    {
        /// <summary>
        /// Registers the target for all the changes.  This must be done before changes can be done.
        /// </summary>
        /// <param name="target"></param>
        void RegisterTarget(TargetType target);

        /// <summary>
        /// Performs a change, but does not commit it yet.
        /// </summary>
        void PreviewChange(Change<TargetType> newChange);

        /// <summary>
        /// Commits the currently previewed change.  It will be added to the undo stack.
        /// </summary>
        void CommitChange();

        /// <summary>
        /// Previews and commits a change in one step
        /// </summary>
        void CommitChange(Change<TargetType> newChange);

        /// <summary>
        /// Undoes the previewed change.
        /// </summary>
        void CancelChange();

        /// <summary>
        /// Undoes the most recent change.
        /// </summary>
        void Undo();

        /// <summary>
        /// Redoes the most recently undone change.
        /// </summary>
        void Redo();
    }
}

Notes on this:

1 – Currently, this service only supports one target.  It could be expanded to have multiple targets and you would tell it what target the change should act upon.

2 – The interface is a higher abstraction than that of the changes.  For example, preview.  Previewing a change calls Do and Notify, but not Finalize.  If you preview a second time before finalizing, it calls, Undo on the old change, and then Do and Notify on the new one.  Finalize gets called when you commit the change.  This is to support the previously-mentioned drag-and-drop scenario.

3 – The ChangeManagerService keeps track of changes that have been done and undone in two stacks.  It support infinite undo, but we could put a limit in.

The end result of all this work:  Encapsulated Object-Oriented changes.  Do/Undo/Redo capability.  And the ChangeManagerService is ready and waiting for more projects!

Next time I’ll talk about an extra we just added to the ChangeManagerService.  Object-Oriented business rules. Awesome.

Silverlight and MVVM

All of Affirma Consulting’s Silverlight projects use the MVVM (Model-View-ViewModel) pattern.  This design pattern is modular, testable, and takes advantage of Silverlight’s powerful data-binding capabilities.

A selection of resources on MVVM and Silverlight:

5 Minute Overview of MVVM

MVVM Light Toolkit

Wikipedia Entry

You can find many, many more with a quick Google search and you’ll quickly learn that arrayed around the central MVVM pattern, people tend to use things like ServiceLocator patterns, variations on Observer or Signals And Slots to perform messaging between ViewModels, and that really no one completely agrees on what MVVM is.  That’s one thing you quickly discover.  There 8 dozen existing MVVM frameworks out there.  They each wire up the references in a different way.  And they each contain a different sampling of satellite features.

For example, what is a ViewModel?  Is it a view into the Model?  Maybe.  It certainly wraps the model data in a form that is useful for the view.  But more than that, it’s a model of the view.  The ViewModel maintains state for the View.  Anything in the View that can change should be bound to a property on the ViewModel.  But now the ViewModel is performing two jobs, which is a violation of singularity of purpose.  So we could split it in two and have a model wrapper and a view state machine.  There’s a reason no one does this.  It’s just too much make-work for the payoff.  When done well, our ViewModels tend to be pretty simple anyway.  Why create roadblocks between the view state and the model state?

This is just the first of many postings we’ll be making on MVVM.  Check back frequently for discussions of the intricacies.