Friday, 17 April 2009

Jafar Husain told me that he was working on a challenge by Eric Lippert. David Anson followed and they posted solutions to the challenge on their blog. I thought it was quite a bit of fun so I quickly wrote something up that I like.

I will copy the problem from Erics website. It challenges you to transform a sequence of strings into a nicely delimited form.

(1) If the sequence is empty then the resulting string is "{}".
(2) If the sequence is a single item "ABC" then the resulting string is "{ABC}".
(3) If the sequence is the two item sequence "ABC", "DEF" then the resulting string is "{ABC and DEF}".
(4) If the sequence has more than two items, say, "ABC", "DEF", "G", "H" then the resulting string is "{ABC, DEF, G and H}". (Note: no Oxford comma!)

He noted he was mostly interested in readable code, so I came up with a nice Linq solution. However, Jafar was unimpressed and noted that performance was still important. I was traversing the sequence too often for his taste. Back to the drawing board and coming up with a less readable, but pretty quick implementation:

string lastWord = String.Empty;

StringBuilder sb = new StringBuilder();
foreach(string s in input)
{
    sb.Append(s);
    sb.Append(", ");
    lastWord = s;
}

int lastWordIndex = (sb.Length -1) - lastWord.Length - 3;

if (lastWordIndex > 0)
{
    Console.WriteLine("{" + sb.ToString(0, lastWordIndex) + " and " + lastWord + "}");
}
else if (sb.Length == 0)
{
    Console.WriteLine("{}");
}
else
{
    Console.WriteLine("{" + sb.ToString(0, sb.Length -2) + "}");
}

 

I like this solution quite a bit. Obviously not optimized the return statements, and the readability is quite a bit worse than my first attempt. But it’s short, only goes over the sequence once and should perform well.

edit: The linq version:

StringBuilder t = new StringBuilder();

            int count = input.Count();

            var middleStrings = input.Where((s, i) => i > 0 && i < count - 1);

            t.Append("{");

            t.Append(input.FirstOrDefault());

            // linq reads better than foreach.
            middleStrings.ToList().ForEach(s =>
                                              {
                                                 t.Append(", ");
                                                 t.Append(s);
                                              });

            if (count > 1)
            {
                t.Append(" and ");
                t.Append(input.LastOrDefault());
            }

            t.Append("}");

            return t.ToString();

Oh well.

Friday, 17 April 2009 05:15:54 (Romance Standard Time, UTC+01:00)  #    Comments [33]  |  Trackback
 Sunday, 19 October 2008

I’m very excited that Silverlight 2 has been released. I’m too new to Microsoft to claim even the slightest involvement, but it’s wonderful to see the excitement both within Microsoft as outside.
It will be interesting to see what will happen with the (already great) uptake of Silverlight by the market.

As I am spending most of my days knee-deep in Xaml nowadays, I always try to find things that will help me be more productive. It happens quite often that I want to select a complete xaml tag. It’s way too much effort to use the mouse to select it, so I often use the control-m-m shortcut to collapse a tag and then select it. However, a few days ago I took 5 minutes to automate this.

image

When you put your mouse somewhere in the Grid tag, and use my macro, you end up with this:

image

You can even put your mouse in the endtag. I bound it to Control-Q and it has made my life that much better!

The macro is as simple as this:

    Sub SelectXMLTagContents()
        DTE.ActiveDocument.Selection.StartOfLine(VsStartOfLineOptions.VsStartOfLineOptionsFirstColumn)
        DTE.ExecuteCommand("Edit.ToggleOutliningExpansion")
        DTE.ActiveDocument.Selection.StartOfLine(VsStartOfLineOptions.VsStartOfLineOptionsFirstColumn)
        DTE.ActiveDocument.Selection.EndOfLine(True)
        DTE.ExecuteCommand("Edit.ToggleOutliningExpansion")
End Sub

It collapses a tag, jumps to the first column, selects the line and then does an uncollapse.

For those using a tool like Karl’s ‘Xaml Power Toys’, it might also be a worthwile addition to their shortcuts.

Sunday, 19 October 2008 21:17:36 (Romance Standard Time, UTC+01:00)  #    Comments [26]  |  Trackback
 Monday, 17 March 2008

I'll probably dedicate a bigger post to this soon, but I wanted to show you a domainmodel, some code and the xml it generates.
What you see here is two attributes that take on quite a bit of work.
EditableBusinessObject implements IEditableObject for you and also allows you to copy the currentvalues to a loadedvalues state.
CreateSerializeSurrogate generates a surrogate class that knows how to deal with loadedvalues and with circular references.
Together, they form the backbone of the client-side of your domainmodel.

Here is an example.

DomainModel:
(notice this is the full class, no other properties are here)

  0 [EditableBusinessObject]
  1 [CreateSerializeSurrogate]
  2 [Serializable]
  3 [DataContract(Namespace = "myNamespace", Name = "Person")]
  4  public class Person
  5 {
  6   [DataMember]
  7   public int IntProperty { get; set; }
  8
  9   [DataMember]
  10   public string StringProperty { get; set; }
  11
  12   [DataMember]
  13   public string StringProperty2 { get; set; }
  14
  15   int neverSetInt;
  16   [DataMember]
  17   public int NeverSetInt
  18   {
  19    get
  20    {
  21     return neverSetInt;
  22    }
  23    set { neverSetInt = value; }
  24   }
  25
  26   [DataMember]
  27   public List<string> StringLijst { get; set; }
  28
  29   [DataMember]
  30   public List<int> IntLijst { get; set; }
  31
  32   public Person()
  33   {
  34    StringLijst = new List<string>();
  35    IntLijst = new List<int>();
  36   }
  37
  38 }
  39

Some testcode:
(notice line 16 where we do a endEdit. If we had cancelled, we would've had a proper rollback)

  0    Person p = new Person();
  1    p.IntProperty = 1;
  2    p.StringProperty = "Ruurd";
  3    p.StringProperty2 = "Boeke";
  4
  5    p.StringLijst.Add("a");
  6    p.IntLijst.Add(1);
  7
  8    (p as IEditableBusinessObject).CopyCurrentToLoaded();
  9
  10    (p as IEditableBusinessObject).BeginEdit();
  11
  12    p.IntLijst.Add(2);
  13    p.StringLijst.Add("b");
  14    p.StringProperty = "Ruurd Boeke";
  15
  16    (p as IEditableBusinessObject).EndEdit();
  17
  18    DataContractSerializer s = new DataContractSerializer(p.GetType(), null, int.MaxValue, false, false, new SubstituteDomainDataContractSurrogate());
  19
  20    string outMessage = GetWellFormedToContract(p, s);

And the generated xml:
(notice how the lists and 'StringProperty' are changed, and see the original value).

<PersonSurrogate xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="myNamespace">
    <IntLijst xmlns:d2p1="http://schemas.microsoft.com/2003/10/Serialization/Arrays">
        <d2p1:int>1</d2p1:int>
        <d2p1:int>2</d2p1:int>
    </IntLijst>
    <IntProperty>1</IntProperty>
    <SerializationID>0</SerializationID>
    <StringLijst xmlns:d2p1="http://schemas.microsoft.com/2003/10/Serialization/Arrays">
        <d2p1:string>a</d2p1:string>
        <d2p1:string>b</d2p1:string>
    </StringLijst>
    <StringProperty>Ruurd Boeke</StringProperty>
    <StringProperty2>Boeke</StringProperty2>
    <OriginalValue_IntLijst xmlns:d2p1="http://schemas.microsoft.com/2003/10/Serialization/Arrays">
        <d2p1:int>1</d2p1:int>
    </OriginalValue_IntLijst>
    <OriginalValue_IntProperty>1</OriginalValue_IntProperty>
    <OriginalValue_StringLijst xmlns:d2p1="http://schemas.microsoft.com/2003/10/Serialization/Arrays">
        <d2p1:string>a</d2p1:string>
    </OriginalValue_StringLijst>
    <OriginalValue_StringProperty>Ruurd</OriginalValue_StringProperty>
    <OriginalValue_StringProperty2>Boeke</OriginalValue_StringProperty2>
</PersonSurrogate>

What is left, is deserializing, maybe propagating the beginedit commands to all children and then create the serverside EF variant.
Oh, and I don't like the originalValue representation. Maybe I'll generate a OriginalValue class to keep it tidy.

Monday, 17 March 2008 22:28:31 (Romance Standard Time, UTC+01:00)  #    Comments [11]  |  Trackback
 Sunday, 16 March 2008

[update: I've updated my project quite a bit, and moved the state to another object. So, the code you are about to see is old!]

In the grand scheme of things, I'm building toward a set of tools that will enable me to use EntityFramework on the server and use the same businessobjects on the client-side, without having to reference EntityFramework at all.
We already have a great domain layer supporting EF, without baseclasses. To use these objects on the client, we will need to take care of changetracking ourselves. When we are done with that, we'll just have to write a custom serializer, that will know how to serialize xml representations of the objects on the client-side, and deserialize on the server and vice versa.

I'll follow up in some post that describes how you can create different versions of your domain layer for use on either client-side or server-side.

The end result

Let's skip to the end result straight away. This is a little test that runs fine:

  0    Person p = new Person();
  1    p.Name = "Ruurd";
  2    p.MyProperty = 10;
  3    p.orders.Add("234");
  4    p.orders.Add("23asdf4");
  5    p.orders.Add("234345zs");
  6
  7
  8    IEditableBusinessObject editablePerson = p as IEditableBusinessObject;
  9
  10    editablePerson.CopyCurrentToLoaded();
  11
  12    editablePerson.BeginEdit();
  13
  14    p.Name = "Boeke";
  15    p.orders.Add("zxcvzxcvzxcvzxcv");
  16
  17    Assert.IsTrue(p.Name == "Boeke");
  18    Assert.IsTrue(p.orders.Count == 4);
  19
  20    editablePerson.CancelEdit();
  21
  22    Assert.IsTrue(p.orders.Count == 3);
  23    Assert.IsTrue(p.Name == "Ruurd");

Just so we are on the same page, we did not have to implement anything on the business object itself. Only use an attribute: the EditableBusinessObjectAttribute. It will take care of everything for ya.

  0 [EditableBusinessObject]
  1 [Serializable]
  2  public class Person
  3 {
  4   public int MyProperty { get; set; }
  5
  6   public string Name { get; set; }
  7
  8   public List<string> orders { get; set; }
  9
  10   public Person()
  11   {
  12    orders = new List<string>();
  13   }
  14
  15 }

Editable business objects

There is already a great usersample available on how to use PostSharp to implement this interface. I took a different route, but you should still check out the sample, because it is actually quite well put together.

My scenario has the following requirements:

  • implement IEditableObject (obviously)
  • Have a way to copy values to a 'Loaded' state: necessary to be able to send the 'original values' to Entity Framework
  • Retrieve that loaded state: will be used by the serializer, to actually create the original value serialization

So, I created the following interface that we will implement using PostSharp:

  0  public interface IEditableBusinessObject : IEditableObject
  1 {
  2   void RegisterFieldAccessAspect(FieldInterceptionAspect aspect);
  3
  4   void CopyCurrentToLoaded();
  5
  6   object RetrieveLoadedState(string FieldName);
  7
  8   bool HasPendingTransaction();
  9 }
  10

To implement, we use the familiar CompositionAspect.

For the real magic, we need to intercept all gets and sets of all fields in the business object.

Intercept field access

A very strong feature of PostSharp is the OnFieldAccessAspect. It allows you to actually intercept field access and route it to something different.
The implementation of IEditableBusinessObject knows when the businessobject is set to beginedit and should notify all fieldaspects. We do this by 'registering' the fieldaspect at the editableBusinessObject. This way, when our object is going to beginEdit mode, all we have to do is iterate our fieldaspects and let them know.

At that point the fieldaspect makes a copy of it's value to the corresponding statebag. If our value was not a value type, we make a deepcopy. I'm contemplating adding support for ICloneable, so we can possibly skip that step.

So, the begin, cancel and endedit methods on the fieldaspect look something like this:

  0   internal void BeginEdit()
  1   {
  2    if (needsBinaryCopy)
  3    {
  4     MemoryStream m = new MemoryStream();
  5     BinaryFormatter b = new BinaryFormatter();
  6     b.Serialize(m, CurrentState);
  7     m.Position = 0;
  8     PendingState = b.Deserialize(m);
  9    }
  10    else
  11    {
  12     PendingState = CurrentState;
  13    }
  14   } 
  15  
  16   internal void CancelEdit()
  17   {
  18    PendingState = null;
  19   }
  20
  21   internal void EndEdit()
  22   {
  23    CurrentState = PendingState;
  24    PendingState = null;
  25   }

And the get and set methods of the field look like this:

  0   public override void OnGetValue(FieldAccessEventArgs eventArgs)
  1   {
  2    IEditableBusinessObject editableObjectImpl = (IEditableBusinessObject)eventArgs.Instance;
  3    editableObjectImpl.RegisterFieldAccessAspect(this);
  4
  5    eventArgs.ExposedFieldValue = editableObjectImpl.HasPendingTransaction() ? PendingState : CurrentState;
  6   }
  7
  8   public override void OnSetValue(FieldAccessEventArgs eventArgs)
  9   {
  10    IEditableBusinessObject editableObjectImpl = (IEditableBusinessObject)eventArgs.Instance;
  11    editableObjectImpl.RegisterFieldAccessAspect(this);
  12
  13
  14
  15    if (editableObjectImpl.HasPendingTransaction())
  16    {
  17     PendingState = eventArgs.ExposedFieldValue;
  18    }
  19    else
  20    {
  21     CurrentState = eventArgs.ExposedFieldValue;
  22    }
  23   }

As you can see, it checks with the instance, whether we have a pending transaction (we have started beginedit). If we do, we write to the pendingstate object, instead of the current state.

I don't feel too comfortable with the code at this point, because I took quite a bit of shortcuts. So I'm not putting that online at this point. However, if you are really interested, let me know in the comments, and I'll clean it up.

Stay tuned, because the next step will be to get this to serialize nicely, with originalvalues and such.

Sunday, 16 March 2008 15:16:14 (Romance Standard Time, UTC+01:00)  #    Comments [2]  |  Trackback
 Wednesday, 05 March 2008

the Oredev-conference posted video's of it's sessions online here.

I've just browsed the sessions that were held at this big conference, and it looks interesting. Many famous names, like Erik Meijer, Joe Duffy, Jimmy Nilsson (I read his book), Mats Helander and many others.

The conference has specific tracks: Java, .Net, Methods & Tools, Test, Project Management, Embedded System, Architecture and User Experience.

So sit back, relax, have a beer and hear great people explain important topics to you.

Just a quick tip: you can only watch the video's inside a browser. If you try to download, you will get a very small file. Open that with notepad and look for the rts: address at the very end. Copy paste the url into a good media player like VLC which knows how to deal with streams, and you will be able to watch more comfortably. I did this, because I could not scale the webversion and I had no way of scrubbing through the video.

kick it on DotNetKicks.com

Wednesday, 05 March 2008 17:48:13 (Romance Standard Time, UTC+01:00)  #    Comments [0]  |  Trackback
 Thursday, 28 February 2008

Just a random piece of code that I thought is handy: when you are experimenting with xml, you probably want to see the xml quickly and easily. For instance, when you are using the DataContractSerializer to serialize a type, you want to see how it looks. But it get's printed on one line!! That's not useful.

Use something like the following code:

            MemoryStream m = new MemoryStream();
            XmlTextWriter tw = new XmlTextWriter(m, Encoding.UTF8);
            tw.Formatting = Formatting.Indented;
            tw.Indentation = 4;
            tw.IndentChar = " ".ToCharArray()[0];
            s.WriteObject(tw, p);
            tw.Flush();
            m.Position = 0;
            StreamReader sr = new StreamReader(m);
            string strOutput = sr.ReadToEnd();
            Debug.WriteLine(strOutput);
 
Where s represents your datacontract serializer.
This outputs glorious xml to the debug.output window:
<Person xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.datacontract.org/2004/07/DomainModel">
    <FirstName>Ruurd</FirstName>
    <LastName>Boeke</LastName>
    <Orders>
        <Order>
            <Amount>5</Amount>
            <ProductID>10</ProductID>
        </Order>
        <Order>
            <Amount>12</Amount>
            <ProductID>11</ProductID>
        </Order>
        <Order>
            <Amount>2</Amount>
            <ProductID>1</ProductID>
        </Order>
    </Orders>
</Person>
Thursday, 28 February 2008 15:06:40 (Romance Standard Time, UTC+01:00)  #    Comments [2]  |  Trackback

I'm a big reflection fan. However, reflection is slow and (for certain actions) requires full-trust. That's a big issue, since that means you can not use it in an unsigned xbap or whatever.

People are finding some cool ways to work around reflection where they can.

Ayende talks about the performance implications of creating objects here, and concludes that reflection might be slow, but you should ask yourself if you really care. If you do, he shows how to use dynamic methods to do the creation for you.

Roger Alsing takes it one step further, and uses Linq to build an expression tree to access private fields. Radical!! I love it. Read it here.
Also note his performance gains:

This approach is also much faster than Reflection.FieldInfo.
I made a little benchmark where I accessed the same field a million times.

The Reflection.FieldInfo approach took 6.2 seconds to complete.
The Compiled lambda approach took 0.013 seconds to complete.
That’s quit a big difference.

But keep in mind that actually compiling the expression is many times slower than reflection.

Thursday, 28 February 2008 01:41:48 (Romance Standard Time, UTC+01:00)  #    Comments [2]  |  Trackback