views:

52

answers:

1

I'm using a library which requires my views to implement an interface, which is only a dependency property and get\set accessor for it. The only difference is the OwnerType in the DP's Register method. AFAIK, duplicate code is bad, and I've forgotten to change OwnerType after pasting several times now :) So I figure I should try and move this up into the base class, and have it determine the type. After some messing around, I got it to work, by initializing it in the constructor, with GetType() to determine the type. The only problem is when the view gets destroyed, and gets recreated later which causes an ArgumentException that the DP is already registered.

  1. Is this refactoring a good idea?
  2. Am I doing it right? :)
  3. If 1 and 2 are true, how can I check if the DP is already registered?

@Carl: I'm not sure if the dependency properties ever were unregistered. I'm not even sure if dependency properties can be unregistered :)

Here was the original class, the code-behind of a xaml view (This and its base class are my creations):

[ViewnameToViewLookupKeyMetadata("StartView", typeof (StartView))]
public partial class StartView : IWorkSpaceAware
{
   public EditorStartView()
   {
       InitializeComponent();
   }


   public static readonly DependencyProperty WorkSpaceContextualDataProperty =
       DependencyProperty.Register("WorkSpaceContextualData", typeof(object), typeof(StartView),
                                   new FrameworkPropertyMetadata((WorkspaceData)null));

   public WorkspaceData WorkSpaceContextualData
   {
       get { return (WorkspaceData) GetValue(WorkSpaceContextualDataProperty); }
       set { SetValue(WorkSpaceContextualDataProperty, value); }
   }
}

The metadata attribute simply associates a lookup string with a type.

I think it works because the register is only ever done once, when view is created the first time.

In the base class the Register seems to have to be in the constructor, so I can use GetType() as the OwnerType. So, when the view is created again, it tries to register again, causing the ArgumentException.

The interface is simple:

public interface IWorkSpaceAware
{
    WorkspaceData WorkSpaceContextualData { get; set; }
}

Found Solution:

I changed the Register OwnerType to typeof(MyViewBase), and put the assignment back in the field.

+1  A: 

It sounds like a good refactoring to me, although there are tradeoffs of having a trivially simple method in each class, versus a slightly complex method in the superclass.

What I don't understand is why the behavior changed when you performed the refactoring. Whatever mechanism was originally in place to un-register a class when its instance is destroyed should continue to work; if it doesn't, then explore why not.

What is the un-registration mechanism? Can you step through it in the debugger, for a class that implements the interface directly? There could by some reflection going on in the library that fails under your refactoring; if so, the simplest thing might be to report the bug to the library author and revert to the duplicate-code approach until it's fixed. With respect to forgetting to change the OwnerType after pasting it, perhaps you could paste it from a snippet with the OwnerType commented out, or empty, or otherwise uncompilable, to force you to fix it quickly.

Carl Manaster