Showing posts with label refactoring. Show all posts
Showing posts with label refactoring. Show all posts

05 August 2010

Fixing CLSA property registration issues in child objects

AKA ‘avoiding the dreaded “Can not register property YourProperty after containing type (YourBaseType) has been instantiated” error message’

Somewhere between CSLA 3.0 en 3.6 a new way of registering properties has become into being:

// old skool CSLA
private string _oldProp = string.Empty;
public string OldProp
{
  get
  {return _oldProp;}	 
  set
  { if (value == null) value = string.Empty;
    if (!_oldProp.Equals(value))
    {
      _oldProp = value;
      PropertyHasChanged("OldProp");
    }
  }
}

//new skool CSLA
private static PropertyInfo NewPropProperty = 
  RegisterProperty(c => c.NewProp);
public string NewProp
{
	get { return GetProperty(NewPropProperty); }
	set { SetProperty(NewPropProperty, value); }
}

In CSLA 4.0 the last style is mandatory, so I started upgrading some objects (while currently using CSLA 3.8.3) in anticipation. So I upgraded my base object

using Csla;

namespace CslaInheritance
{
  public abstract class MyBaseClass : BusinessBase<MyBaseClass>
  {

    protected static PropertyInfo<string> MyProp1Property = 
        RegisterProperty<string>(c => c.MyProp1);
    public string MyProp1
    {
      get { return GetProperty(MyProp1Property); }
      set { SetProperty(MyProp1Property, value); }
    }

    protected static PropertyInfo<string> MyProp2Property = 
        RegisterProperty<string>(c => c.MyProp2);
    public string MyProp2
    {
      get { return GetProperty(MyProp2Property); }
      set { SetProperty(MyProp2Property, value); }
    }
  }
}
and then my child object
using Csla;

namespace CslaInheritance
{
  public abstract class MyConcreteClass1 : MyBaseClass
  {
    protected static PropertyInfo<string> ConcreteProp1Property = 
      RegisterProperty<string>(c => c.ConcreteProp1);
    public string ConcreteProp1
    {
      get { return GetProperty(ConcreteProp1Property); }
      set { SetProperty(ConcreteProp1Property, value); }
    }

    protected static PropertyInfo<string> ConcreteProp2Property =
      RegisterProperty<string>(c => c.ConcreteProp2);
    public string ConcreteProp2
    {
      get { return GetProperty(ConcreteProp2Property); }
      set { SetProperty(ConcreteProp2Property, value); }
    }
  }
}

And then I noticed something odd: according to the compiler, ConcreteProp1 and ConcreteProp2 were not defined. Even worse is the situation when you choose to upgrade your properties not using lambda expressions, but PropertyInfo objects, like this:

    protected static PropertyInfo<string> ConcreteProp3Property =
      new PropertyInfo<string>("ConcreteProp3Property");
    public string ConcreteProp3
    {
        get { return GetProperty(ConcreteProp3Property); }
        set { SetProperty(ConcreteProp3Property, value); }
    }
because this will compile - and run. Until you create a second child class MyConcreteClass2, instantiate it, then instantiate a MyConcreteClass1 – and then you will get a cryptical runtime error message saying “Can not register property ConcreteProp1Property after containing type MyBaseClass has been instantiated”.

Fortunately the CSLA framework comes with sources, and after some rooting around I found the culprit, if you can call it that, in Csla.BusinessBase:

protected static PropertyInfo<P> 
  RegisterProperty<P>(Expression<Func<T, object>> propertyLambdaExpression)
{
  PropertyInfo reflectedPropertyInfo = 
    Reflect<T>.GetProperty(propertyLambdaExpression);

  return RegisterProperty(Csla.Core.FieldManager.PropertyInfoFactory.Factory.Create<P>(
    typeof(T), reflectedPropertyInfo.Name));
}

Although MyConcreteClass1 inherits from MyBaseClass, MyBaseClass inherits in turn from templated class BusinessBase<MyBaseClass>. Therefore, in RegisterProperty called from MyConcreteClass1 T is still MyBaseClass. It does not matter that I actually called it from a child class. So what happens is that all the statics are defined in the base class MyBaseClass. If you are using the lambda variant to register, the compiler saves your *ss, but if you use the PropertyInfo method something weird happens. Remember, statics in a class are initialized as soon as you touch any one of statics. So what happens is: you instantiate your concrete child class, immediately the statics of both the concrete and the base class are initialized, and all the properties are registered in the base class. If you try to instantiate a second concrete child class, Csla finds that your base class properties are already initialized, and the dreaded “Can not register property ConcreteProp1Property after containing type MyBaseClass has been instantiated” error message appears.

Now you can of course change the way you implement classes. I might make MyBaseClass generic as well, then T changes along. But when upgrading an existing API out of a situation in which direct inheritance used to be perfectly legal, it’s a different story.

There are actually two ways out of this. The first one is: use PropertyInfo, but explicitly name the object type to which the property belongs

protected static PropertyInfo<string> ConcreteProp3Property =
  RegisterProperty(typeof(MyConcreteClass1), 
  new PropertyInfo<string>("ConcreteProp3Property"));
public string ConcreteProp3
{
    get { return GetProperty(ConcreteProp3Property); }
    set { SetProperty(ConcreteProp3Property, value); }
}

This works, but I like the solution below better, because that uses lambda expressions again and so your friend the compiler ;-) can help you catch typo’s. The only way I see to realize that is to add a static method at the bottom of your class

private static PropertyInfo<T> RegisterPropertyLocal<T>(
  Expression<Func<MyConcreteClass1, object>> propertyLambdaExpression)
{
  var reflectedPropertyInfo = 
  Reflect<MyConcreteClass1>.GetProperty(propertyLambdaExpression);
  return RegisterProperty(typeof(MyConcreteClass1),
    Csla.Core.FieldManager.PropertyInfoFactory.Factory.Create<T>(
    typeof(MyConcreteClass1),
    reflectedPropertyInfo.Name);
}
and then register your properties like this from now on:
protected static PropertyInfo<string> ConcreteProp1Property = 
  RegisterPropertyLocal<string>(c => c.ConcreteProp1);
public string ConcreteProp1
{
  get { return GetProperty(ConcreteProp1Property); }
  set { SetProperty(ConcreteProp1Property, value); }
}

The drawback of this solution is, of course, that you have to define a static RegisterPropertyLocal in every inherited class you define. But at least you will be saved from typos and weird runtime errors.

Now you are ready to upgrade, but I would recommend recording some macros to do the actual syntax change, unless you are very fond of very dull repetitive typing jobs ;-)

28 February 2010

Injecting logic in the middle of an algorithm using “Func<T>” function parameters

Sometimes you run into a situation in which you have a very similar complex pieces of logic, that only differ somewhere deep inside. This happens especially when you are dealing with legacy code that requires all kinds of weird initializers. Consider the following example, which is similar to something I ran into deep down in a CSLA library:

private void DataPortal_Fetch(string a, string b, string c)
{
  var helper = new LoaderHelper();
  helper.Init();
  LegacyObjectCollection result = 
OldStaticHelper.GetByThreeStrings( a, b, c); IsReadOnly = false; result.ForEach(p => Add(SomeNewObject.Get(p, helper))); RaiseListChangedEvents = false; IsReadOnly = true; } private void DataPortal_Fetch(string a, int n) { var helper = new LoaderHelper(); helper.Init(); LegacyObjectCollection result = OldStaticHelper.GetByOtherKeys( a, n); IsReadOnly = false; result.ForEach(p => Add(SomeNewObject.Get(p, helper))); RaiseListChangedEvents = false; IsReadOnly = true; }

The idea clearly was to call some legacy code and transform this into a list of “SomeNewObject”. But the annoying thing about the legacy code was that all kinds of helpers needed to be initialized before OldStaticHelper could be called. And then the logic of transforming the data had been duplicated as well. There are a number of ways to refactor this, but because I was fooling around with functional programming concepts at the time, I tried the following, which almost worked:

private void DataPortal_Fetch(string a, string b, string c)
{
  FetchData(OldStaticHelper.GetByThreeStrings( a, b, c)); 
}

private void DataPortal_Fetch(string a, int n)
{
  FetchData(OldStaticHelper.GetByOtherKeys( a, n));
}

private void FetchData(Func<LegacyObjectCollection> loaderMethod)
{
  var helper = new LoaderHelper();
  helper.Init();
  LegacyObjectCollection result = loaderMethod();
  IsReadOnly = false;
  result.ForEach(p => Add(SomeNewObject.Get(p, helper)));
  RaiseListChangedEvents = false;
  IsReadOnly = true;
}

Although this compiled an ran, it did not work as expected. Upon calling “FetchData” the OldStaticHelper.GetBy… method was instantly executed, in stead of of when “result = loaderMethod()” was called. And I just stated that it would not work unless the “helper” code was initialized. Thus, I needed to use delegates:

private void DataPortal_Fetch(string a, string b, string c)
{
  FetchData(() => OldStaticHelper.GetByThreeStrings( a, b, c)); 
}

private void DataPortal_Fetch(string a, int n)
{
  FetchData(() => OldStaticHelper.GetByOtherKeys( a, n));
}
Or, for those not familiar with the lambda syntax:
private void DataPortal_Fetch(string a, string b, string c)
{
  FetchData(delegate { return OldStaticHelper.GetByThreeStrings( a, b, c)}); 
}

private void DataPortal_Fetch(string a, int n)
{
  FetchData(delegate { return OldStaticHelper.GetByOtherKeys( a, n)});
}
Using this technique you can 'inject' a piece of logic into a larger algorithm, eliminating the need to duplicate code or making all kinds of in-between data sets

16 March 2008

JSON services revisited: using a Dictionary as a generic parameter

Somebody at Microsoft deserves a Nobel Prize. Well, that is maybe a bit strong, but I ran into the problem that I wanted to create JSON scriptserver that would accept a 'parameter bag' of unknown size and type. I expected problems in the serialization, since Javascript typing is at best a bit lax, but it turns out that when you define a web service with a parameter of type Dictionary<string, object> dict, the JSON serializer automatically derives the object types from the javascript data! It works like this: suppose we define the following method:
[WebMethod]
public string DictMethod(Dictionary<string, object> dict)
{
  StringBuilder b = new StringBuilder("C# reports<BR/>");
  foreach( string s in dict.Keys )
  {
    b.AppendFormat(string.Format("{0}:{1}={2}<BR/>", s, dict[s].GetType(), 
                   dict[s]));
  }
  return b.ToString();
}
We can call this method from javascript like this
<script type="text/javascript">
  function LoadDict()
  {
    dict = new Object();
    dict["test1"] = "Joost";
    dict["test2"] = 21;
    dict["test3"] = true;
    dict["test4"] = 9999999999;
    dict["test5"] = new Date(2008,09,12,13,14,00);
    DictService.DictMethod( dict, ProcessResult );
  }

  function ProcessResult( WebServiceResult )
  {
    document.write( WebServiceResult );
  }
</script>
If you attach the LoadDict javascript function to some client side event (The OnClientClick of a button for example) and launch it, you will see the following output: C# reports test1:System.String=Joost test2:System.Int32=21 test3:System.Boolean=True test4:System.Int64=9999999999 test5:System.DateTime=12-10-2008 11:14:00 So you can see, the javascript string converted into a true .NET string, the value 21 into an Int32 - but the value 9999999999 is too long for an int and is converted into a Int64, a.k.a. long - I really like that one, for it shows true craftmanship of the programmer ;-). The "true" javascript value is converted into a Boolean finally, the javascript Date is converted into a neat DateTime. And presto, all your stuff is converted into real .NET objects. Of course, you should always used typed parameters when possible, but for some generic solutions this may come in very handy. Complete code downloadable here.

04 March 2008

Simplyfying refactoring by making things obsolete

A very simple one I ran into today - when you are refactoring things, sometimes old methods are no longer required, but for the sake of backward compatiblity your want to retain them. To make sure your own code no longer calls the deprecated method, simply use the ObsoleteAttribute:
[ObsoleteAttribute("Warning you want the compiler to give")]
public void ObsoleteMethod()
{
  // ....
}
If you now recompile your program, every call to ObsoleteMethod displays the message "Warning you want the compiler to give" in the output window - you might want to change that message to something more useful ;-).