Carlos Ble

Carlos Ble

I am a professional software developer, I solve problems.

I also teach and mentor developers to build better software.

Working as an independent professional since 2009.

Can I help you?

  • Do you need high quality tailor-made software?
  • Need training on TDD, clean code or refactoring?
  • Is it risky? do you need advise?
  • May I pair with you to write better code?

Events

Upcoming public training courses:

  1. [in English] May 5, 6 & 7
    TDD - Train the Trainers (iSQI)
    Potsdam, Berlin
  2. [en Español] 23, 24 y 25 de Abril.
    Curso de TDD con examen de certificacion iSQI
    Madrid
  3. [en Español] 29, 30 y 31 de Octubre.
    Curso de TDD con examen de certificacion iSQI
    Madrid

Conferences:

  1. I'll be at SocratesUK 2014
  2. I'll be at the London Test Gathering Workshops.

Archive for November, 2007



Slides: http://www.carlosble.com/downloads/boxerp/boxerpSummit.zip

See you there!

There you go!: http://boxerp.org

I have a hopefully-temporary problem in 1 hand caused 4 2much typing so that is all 4 now, I need holidays.

Cheers

   1:  class Program
   2:  {
   3:      // sample invocation:  "([^a-z|A-Z|0-9])+" "9asdf(sss*df" "_"
   4:      // return:  Substitution : 9asdf_sss_df
   5:      static void Main(string[] args)
   6:      {
   7:          Regex regex = new Regex(args[0]);
   8:          Console.WriteLine(args[0]);
   9:          MatchCollection matches = regex.Matches(args[1]);
  10:          foreach (Match match in matches)
  11:          {
  12:              Console.WriteLine("Match: " + match.Value);
  13:              foreach (Group group in match.Groups)
  14:              {
  15:                  Console.WriteLine(String.Format("  Group (success = {0}): {1}", group.Success, group.Value));
  16:                  foreach (Capture capture in group.Captures)
  17:                  {
  18:                      Console.WriteLine(String.Format("     Capture: {0}", capture.Value));
  19:                  }
  20:              }
  21:          }
  22:          Console.WriteLine("--- Substitution : " + regex.Replace(args[1], args[2]));
  23:      }
  24:  }

Maybe some day I'll find the time to figure the groups and caputres out. They don't work as in Perl or Python :-(

Mono Summit 2007

We're lucky this year because the Mono Summit is in Madrid. I'm in Dublin actually but the flights are cheap this time. I'm happy because the organization have given me the opportunity to present Boxerp 0.2 there. Here you go the schedule and the site:

  1. http://www.mono-project.com/MonoSummit2007
  2. http://www.mono-project.com/Mono_Summit_2007_Schedule

I'll arrive to Madrid on Thursday evening and give the presentation on Friday and I'll spend the weekend in the city. This is gonna be my first talk in English so I maybe should go there almost drunk because is the only way for me to be really fluent in English ;-) .
I have some friends in Madrid that I'd like to meet so if you read this, please send me an email to do so.

Thanks a lot to the Mono Summit staff!!! Now it's time to work hard in the release, I have to do it before the presentation

Last month I went to Tenerife, to give a presentation at the university I studied (Universidad de La Laguna). I talked about Boxerp 0.2 which hasn't been released yet, although it will be released this month, hopefully. People treated me very well there as usual. I can only say thanks to everybody for everything. Special thanks to Rene and Alberto for recording and digitizing the presentation. You can find the videos here: http://boxerp.org/doku.php?id=videos

Thanks a lot to Marcos, Goyo, Felix and Jordi, they made this presentation possible ;-)
The people of Secretariado del Software Libre are doing an impressive work in Bardinux in addition to many other projects. It has been very nice to be there for a while. This presentation is in Spanish, I hope to record one in English soon.

Update: Jeremy has fixed the english mistakes and we'll update the article from now in the Boxerp wiki: Check it out here


This article tryes to describe the implementation of two AOP mechanisms that generate classes on runtime inheriting from base ones and adding extra functionality to them without the need for changing the base class code. We're using this in Boxerp to make the business objects fully bindable to the UI. To understand the problem you have to understand databinding in WindowsForms at least. Let say we have a business object (the base class) like this:

   1:  [Serializable]
   2:  public class SimpleBusinessObject
   3:  {
   4:      private string _name;
   5:      private string _description;
   6:      private int _age;
   7:  
   8:      public virtual string Name
   9:          {
  10:          get
  11:          {
  12:              return _name;
  13:          }
  14:          set
  15:          {
  16:              _name = value;
  17:          }
  18:      }
  19:      public virtual string Description
  20:          {
  21:          get
  22:          {
  23:              return _description;
  24:          }
  25:          set
  26:          {
  27:              _description = value;
  28:          }
  29:      }
  30:      public virtual int Age
  31:          {
  32:          get
  33:          {
  34:              return _age;
  35:          }
  36:          set
  37:          {
  38:              _age = value;
  39:          }
  40:      }
  41:      public SimpleBusinessObject()
  42:      {
  43:      }

We can bind the object to the UI (say, 3 text boxes) straight away so that the UI will read the values of the object at the moment of the binding and then the object will be updated everytime the text boxes are changed. But, what happen if we update the object from code?. The UI won't get refreshed. In order for the UI to get refreshed, the object has to implement the System.ComponentModel.INotifyPropertyChanged and throw the PropertyChanged event everytime a property is changed. So you end up writing code that has to do with the UI in your business object:

   1:      public virtual string Name
   2:          {
   3:          get
   4:          {
   5:              return _name;
   6:          }
   7:          set
   8:          {
   9:              _name = value;
  10:                          if (PropertyChanged != null)
  11:                          {
  12:                             PropertyChanged(this, new PropertyChangedEventArgs("Name");
  13:                          }
  14:          }
  15:      }

Well, what we're doing with Boxerp.Client.DynamicPropertyChangedProxy, is taking the base class, and generating another class in runtime, that inherits it, implements the INotifyPropertyChanged and modify the properties setters code to throw the PropertyChanged event.

BindableWrapper myFullyBindableObject = new BindableWrapper(mySimpleBusinessObjectInstance);

In addition, we are keeping track of the changes in the business object so everytime the property is changed we save a snapshot of the object in a queue and we are able to undo, and redo changes:

myFullyBindableObject.Undo();

You don't have to change your business object, it does not contain UI code, just business logic. Now lets deep into the implementation details as they are really complex and interesting. At the same time I'll explain the details of the Castle.DynamicProxy2 implementation (partially). The capability of creating new types (System.Type) in runtime is performed though Reflection.Emit. You have to write CIL code, that is pretty much like an assembler and this is reasonable as the application is running and it can't compile C# code. To write CIL code is nothing intuitive at the begining so I've developed the dynamic proxy by writing the desired code in C#, disassembling it with ILDASM, figuring it out and writing the CIL. Most of the time, the dissasembled is exactly what you have to write in the CIL program. In the Boxerp.Client.DynamicPropertyChanged implementation we've writted naived CIL like this:

   1:  mthdIL.Emit(OpCodes.Nop);
   2:  mthdIL.Emit(OpCodes.Ldarg_0);
   3:  mthdIL.Emit(OpCodes.Ldfld, eventHandler);
   4:  mthdIL.Emit(OpCodes.Ldnull);
   5:  mthdIL.Emit(OpCodes.Ceq);
   6:  mthdIL.Emit(OpCodes.Ldc_I4_0);
   7:  mthdIL.Emit(OpCodes.Ceq);
   8:  mthdIL.Emit(OpCodes.Stloc_0);
   9:  mthdIL.Emit(OpCodes.Ldloc_0);
  10:  mthdIL.Emit(OpCodes.Ret);

This is because we're not writing a generic dynamic proxy but just a proxy that extends the base type and makes it implement the INotifyPropertyChanged (actually the ICustomNotifyPropertyChanged that inherits from the former one). However, what we are really creating is a double proxy: the first one is this and the second one is performed by Castle.DynamicProxy2 (DP2). The second overrides the object properties so that the access to them is intercepted and you can fire the events. The code of DP2 is brilliant. They don't write CIL code directly but using an impressive API that makes the code much more clean and understable:

   1:  MethodEmitter getObjectData = emitter.CreateMethod("GetObjectData",               typeof(void), arg1, arg2);
   2:  LocalReference typeLocal = getObjectData.CodeBuilder.DeclareLocal(typeof(Type));
   3:  getObjectData.CodeBuilder.AddStatement(
   4:     new AssignStatement(typeLocal, new MethodInvocationExpression(null,
   5:         typeof(Type).GetMethod("GetType", get_type_args),
   6:                new ConstReference(
   7:                       typeof(ProxyObjectReference).AssemblyQualifiedName)
   8:                           .ToExpression(),
   9:                new ConstReference(1).ToExpression(),
  10:                new ConstReference(0).ToExpression())));
  11:  getObjectData.CodeBuilder.AddStatement(
  12:    new ExpressionStatement(new MethodInvocationExpression(
  13:        arg1, typeof(SerializationInfo).GetMethod("SetType"),
  14:            typeLocal.ToExpression())));

DP2 is a generic proxy that allows you to apply the Interception pattern easily. You can read about that in the Castle documentation. It is very powerful and stable.

So far so good. Now there is a big issue with the dynamic types: The Serialization.
The BinaryFormatter needs to load the type that is going to be serialized and specially deserialized from its assembly. The assembly is dynamic and it is created everytime we run the application so we could not deserialized a dynamic type that was serialized on a former execution of the application. And even worse, we can't send the object to a remote point because the remote point won't have the dynamic assembly so I won't be able to deserialize. We've copied the solution that DP2 implements in DPCP, and I think that withouth DP2 it would have been really difficult to find it out. So DPCP also makes the base class implement the ISerializable interface. The tipical and right implementation of ISerializable would be this:

   1:  public class MySerializableClass : ISerializable
   2:  {
   3:    // Deserilization constructor
   4:    protected MySerializableClass(SerializationInfo info, StreamingContext c)
   5:    {
   6:         object[] data = (object[])info.GetValue("_serializedData",
   7:             typeof(object[]));
   8:         MemberInfo[] members =
   9:             FormatterServices.GetSerializableMembers(this.GetType());
  10:         FormatterServices.PopulateObjectMembers(this, members, data);
  11:    }
  12:  
  13:    // the method that is invoked at the serialization
  14:    public virtual void GetObjectData(SerializationInfo info, StreamingContext context)
  15:    {
  16:         MemberInfo[] serializableMembers =
  17:             FormatterServices.GetSerializableMembers(this.GetType());
  18:         object [] data = FormatterServices.GetObjectData(this,
  19:             serializableMembers);
  20:         info.AddValue("_serializedData", data);
  21:    }
  22:  }

If you implement the ISerializable interface by reading the class fields using reflection (this.GetType().GetField(...)) you won't get the fields that are inherited from base classes because it is not possible. So this is a better way to do it. However this implememtation don't serialize static fields, so you have to take that into account as well.
Unfortunately this implementation does not avoid the need for loading the assembly so we are still in the same issue. The work around for this, is to tell the BinaryFormatter to serialize a different class, not this one. We can relay on another class, which is not dynamic, to be serialized and deserialized, and, get it in charge of the deserialization of the dynamic class. Let's see the implementation of that class in DPCP:

   1:      [Serializable]
   2:      public class DynamicProxyHelper : IObjectReference, ISerializable, IDeserializationCallback
   3:      {
   4:          private object _proxy;
   5:          private Type[] _argumentsForConstructor;
   6:          private object[] _valuesForConstructor;
   7:          private readonly SerializationInfo _info;
   8:          private readonly StreamingContext _context;
   9:          private string _baseTypeName;
  10:          private Type _baseT;
  11:  
  12:          public DynamicProxyHelper(SerializationInfo info, StreamingContext context)
  13:          {
  14:              _info = info;
  15:              _context = context;
  16:  
  17:              _argumentsForConstructor = (Type[])info.GetValue(DynamicPropertyChangedProxy.ARGUMENTS_TYPES4CONSTRUCTOR, typeof(Type[]));
  18:              _valuesForConstructor = (object[])info.GetValue(DynamicPropertyChangedProxy.VALUES4CONSTRUCTOR, typeof(object[]));
  19:              _baseTypeName = (string)info.GetValue(DynamicPropertyChangedProxy.OBJECT_BASE_TYPE, typeof(string));
  20:              bool isBusinessObj = (bool)info.GetValue(DynamicPropertyChangedProxy.IS_BUSINESS_OBJECT, typeof(bool));
  21:              _baseT = Type.GetType(_baseTypeName, true, false);
  22:              Type firstProxyType;
  23:              object[] baseMemberData = (object[])_info.GetValue(DynamicPropertyChangedProxy.SERIALIZED_DATA, typeof(object[]));
  24:              ProxyGenerator generator = new ProxyGenerator();
  25:  
  26:              if (isBusinessObj)
  27:              {
  28:                  // the business objects have to have a default constructor
  29:                  firstProxyType = DynamicPropertyChangedProxy.CreateBusinessObjectProxy(_baseT, _argumentsForConstructor);
  30:                  _proxy = generator.CreateClassProxy(firstProxyType, (IInterceptor[])baseMemberData[0]);
  31:              }
  32:              else
  33:              {
  34:                  // if it is not a business object then it has to be a BindableFields class which constructor has always an interceptor
  35:                  firstProxyType = DynamicPropertyChangedProxy.CreateBindableWrapperProxy(_baseT, _argumentsForConstructor, _valuesForConstructor);
  36:                  _proxy = generator.CreateClassProxy(firstProxyType, (IInterceptor[])baseMemberData[0], _valuesForConstructor);
  37:              }
  38:  
  39:  
  40:  
  41:          }
  42:  
  43:          #region IObjectReference Members
  44:  
  45:          public object GetRealObject(StreamingContext context)
  46:          {
  47:              return _proxy;
  48:          }
  49:  
  50:          #endregion
  51:  
  52:          #region ISerializable Members
  53:  
  54:          public void GetObjectData(SerializationInfo info, StreamingContext context)
  55:          {
  56:              // do nothing 
  57:          }
  58:  
  59:          #endregion
  60:  
  61:          #region IDeserializationCallback Members
  62:  
  63:          public void OnDeserialization(object sender)
  64:          {
  65:              object[] baseMemberData = (object[]) _info.GetValue (DynamicPropertyChangedProxy.SERIALIZED_DATA, typeof (object[]));
  66:              MemberInfo[] members = FormatterServices.GetSerializableMembers (_proxy.GetType());
  67:              FormatterServices.PopulateObjectMembers (_proxy, members, baseMemberData);
  68:          }
  69:  
  70:          #endregion
  71:      }

In the deserialization constructor of the class, we take the necessary that to recreate a proxy, and at the end, the OnDeserialization method is called and it populates the proxy (dynamic type) with the data it sent.
The whole process is as follows:

The dynamic type implements ISerializable and its GetObjectData method its executed on the serialization. In that method we put all the required information for the deserialization into the info object and also we tell the BinaryFormatter that it should serialize the DynamicProxyHelper and not the current type (through the SerializationInfo.SetType method):

   1:  info.SetType(typeof(DynamicProxyHelper));
   2:  MemberInfo[] serializableMembers =
   3:       FormatterServices.GetSerializableMembers(this.GetType());
   4:  object[] data = FormatterServices.GetObjectData(this, serializableMembers);
   5:  info.AddValue(DynamicPropertyChangedProxy.SERIALIZED_DATA, data);

Then the DynamicProxyHelper is serialized. At the deserialization it is able to create again a proxy and it is able to populate the fields of the proxy. In Castle.DynamicProxy2, the helper is the Castle.DynamicProxy/Serialization/ProxyObjectReference class. The Castle.DynamicProxy/Generators/BaseProxyGenerator contains the first part of the GetObjectData implementation and the ClassProxyGenerator contains the second part. It takes into account that, if the base class implements the ISerializable, we have to call its GetObjecData method first. DPCP behaves equally.
Here you go a question to see if you have understood this:

Will the deserialization constructor of the dynamic type (proxy) be ever called?
The answer is, NO.

The dynamic type takes part of the serialization process but not in the deserialization.

This article will have future updates and explanations. The license of DPCP and the whole Boxerp project is BSD and the first release contanining all this features will be launched very soon (0.2).
CastleProject license is Apache2 and the version 1.0 RC3 was released few days ago.
Here you have the files:

Boxerp:

CastleProject: