Wednesday, December 22, 2010

Coding practices, part 1

.. hold on tight

Various have been the places I have worked at and even more so the people I have worked with. Sometimes it was a good experience where both parties benefited, but sometimes it was a struggle.
One of the downsides is that I have had to work with code produced to varying standards if there was something like a standard at all. In this little series of blog posts I will highlight some of the examples that I have encountered over the years. Most of these are related to C# but probably apply to more situations. If so, you have my condelances.
Make me search like forever
One of the great things of freedom in structuring classes, codes and files is that you can do things in all kinds of ways. That is exactly the downside as well. You can put things all over the place without any logical connection between them:
  • Put multiple public classes in one file.
  • Name the file different from the class that’s inside.
  • Don’t use the namespace according to the folder the file is in.
  • Name the project different from the name of the assembly.
  • Put in a folder with yet a different name.
  • Cherry on the cake: make it completely different in source control where possible.
I only hope that this covers all possible obscurity.
Taking for granted that we now know every possible option
Let's consider a simple enumeration giving us a choice of direction.
public enum Direction
{
    Left,
    Right
}
Now let's say you are at least clever enough to consider using switch-statement instead of a if-statement to implement this in your code. Still, you have multiple ways to make this work or not.
Suppose you need this in a method that returns something based on the direction.
Good
Be sure to have a default option.
switch (direction)
{
    case Direction.Left:
        return SomethingLeft();
    case Direction.Right:
        return SomethingRight();
    default:
        return null;
}
Better
Maybe returning a null-value is not desired or maybe even SomethingLeft() can return null then it's probably better to throw an exception.
switch (direction)
{
    case Direction.Left:
        return SomethingLeft()
    case Direction.Rightt:
        return SomethingRight();
    default:
        throw new ArgumentOutOfRangeException("direction");
}
Bad
Somepeople think that writing less code is better.
switch (direction)
{
    case Direction.Left:
        return SomethingLeft();
    default:
        return SomethingRight();
}
What now if someone thinks we shoud be able to go 3D?
public enum Direction
{
    Left,
    Right,
    Up,
    Down
}
A right-handed Cartesian coordinate system, il...Image via Wikipedia
Or maybe an old sailor becomes architect and decides to use this:
public enum Direction
{
    East,
    West,
    North,
    South
}
We could do something like global search and replace or a refactor action, but the bad code will probably not do what we want.
Seen all these
I have seen the above examples and have frowned at them. I have improved the code where possible and have given up on trying to educate some of the people who wrote the code.
More examples will follow.
Enhanced by Zemanta

Monday, November 22, 2010

A very weird bug

.. with an even weirder resolution

The other day I was working with a consultant from another firm to try connect our systems together. Previously we had exchanged WSDLs and even a stub service so we didn't expect to many problems implementing the real stuff.

The other client had brought his own laptop and that was quickly hooked up into the network. That was an easy start.

But ...

Things started to get really weird when I tried to connect my client app to his service. To make it a little more clear to you all: the service was a .NET 3.5 WCF Service and I was consuming it using a .NET 2.0 webservice client. The 2.0 bit was manadtory as our application is still limited to that version of the .NET Framework.

We were greeted with the following very weird error:

The message with Action 'http://tempuri.org/ITheOtherService/GetObjects' cannot be processed at the receiver, due to a ContractFilter mismatch at the EndpointDispatcher. This may be because of either a contract mismatch (mismatched Actions between sender and receiver) or a binding/security mismatch between the sender and the receiver. Check that sender and receiver have the same contract and the same binding (including security requirements, e.g. Message, Transport, None).

Googling it didn't give me a clue.

To add some more info: he was running his own domain and Active Directory on his machine. And I also had to use a NetworkCredential to get access to the service. I could see the MEX output in Internet Explorer (using the correct credentials) so connection was verified. We were connecting using the IP address of his machine.

Question marks all over

Completely baffled he gave me a test application that he had used to test the setup with a colleague in his office. We got a error message that prompted me to add the hostname and IP address to my hosts file. We had an error about linked XSD files that couldn't be found because the hostname could ot be resolved.

After that little hack we had no problem making call and getting results. Completly stunned we stared at our screens. OK, fine by me.

The big application where all the work was made still did not function. Still showing the same error message.

Another even simpler app was created, making a simple call to the service. And it worked. But still not in the big application we needed to hook up.

Details are the devil's hiding place

In another test run I then saw that I had configured the big application using the IP address. The hostname was not yet in the hosts file when I first configured the service address.

The test applications we used both of them used the host name in stead of the IP address and they worked.

After having changed the configuration to use the hostname evrything started working.

I still haven't found out why it did.

Well, who cares?

We then continued to do the testing and had to make onlysome small changes as we both had done a great job in building our apps to mutual specs. So, it was all in all a great success. But something keeps itching me.

Well, who cares why it worked with hostnam? Well I do care! I have no real idea what the reason is why it worked one way and not the other. SO, if any of you can point me to the reason of this, please leave it in a comment.

Also, maybe this story helps you to solve your weird error. If so, please leave a commoent.

Monday, November 15, 2010

A discussion about creation

.. too early in the morning

Every now and then I am invited to a job interview to sit at the employers side of the table.'That is kind of fun as well. I do enjoy sitting on the other side, because I have the feeling that I am the one who is to make the decision whether to take the position or not. Once they have invited me for the interview I am pretty close to getting hired. At least that is the mood I try to get myself into on most of these occasions.

As I am a developer I mostly attend the interviews for developers. I am usually the ally of the prospect in that sense. The manager that sits there as well is most of the time a non-developer. Someone who knows we need someone with .NET and C# skills, but has no real idea what that means. I am there to see if he or she has any real developer's skills.

Questions to ask

A colleague of mine has very goo question to ask the candidate. He tells the candidate that we would like the manager start programming or at least understand some more what we are doing. One of the things the manager still can not understand is, what is Object Orientation? Can the candidate explain that so the manager can understand the concept. I have heard some hilarious answers to that question. One of the apparent advantages of Object Orientation is that you can spread the objects across multiple servers. The same candidate explained some of the aspects of OO with a dog as an example, one the methods could be Bark() or Sit(). When asked how one would distribute such behavior across multiple servers he fell silent.

Another good and slightly more tricky question to ask is about difference between the terms class, type and object. I must admit that I had to think about that one to come up with a good example. I propose the following example of a Person class, with as properties: first name, last name and birth date. Let's pass those along in the constructor and you get to the following code:

Person person = new Person(firstname, lastname, birth date);

The first word "Person" is the type of the object "person" being created. The class is Person in which a.o. the used constructed is found.

All right, purists, kill me in the comments, but it gently.

A question to ask

I then started to let my mind go wandering where it will go.

I thought about namespaces. I happened to have been in some discussion with namespaces and doing it better than it was in common practice at this job I was at.

The class Person would be in something called

  • Human

Then I started expanding:

  • Nature.Human
  • Earth.Nature.Human
  • Creation.Nature.Human
  • God.Creation.Nature.Human

Hmm, sounds like intelligent design. Note that I haven't named God, that would turn off some other Persons from the namespace Hardcore.Christian.God.Creation.Nature.Human.

Or for those rather having the Evolution Theory, it could be something like:

  • Darwin.Evolution.Mammal.Primate.Human

But working along these ideas, ultimately, all namespaces would be positioned below God or Darwin. That would be strange idea. And what about the Flying Spaghetti Monster?

The God Class

Then I found myself wondering about the God class. "You should never create a God class." It must be one of the ten Developer's Commandments. Which namespace would that God class be in? I became stuck at this point. I at least understand now why I should never creat a God class, because there is no namespace to put it in.

On top of that does the God class derive from object? Or from a divine object? Or the other way around: does object derive from God?

Philosphical

So, there I was completely philosophical before 9 in the morning. Suffice to say, I didn't get much work done all day. Especially no Divine Work.

Please someone help! Define devine!

Friday, November 12, 2010

Scope creep can be nasty

.. but scope run seems worse

I've had it happen way too often on me: scope creep. Slowly, but surely small things get added and one moment you notice that way too much things are happening and need to be done on that small project.

I have been there and seen it and let it happen and still let it happen way too often. Almost every project scope creep comes creeping in.

But it can be worse

What is also possible in these 'agile' processes that are so hip these days that scope creep can go so fast that it not just adds some extra, elaborate features, but that it changes the complete application you are working on.

Sounds like horror?

Maybe this sounds like horror to you, but it can be a blessing as well. It prevents the moment where the client is proudly presented with the end product and then tells you that it is by no way what he wants.

To me it has been a good experience.

I know, I know

.. it's been too silent

Lately I have been busy with loads of stuff and hardly had the time to write some stuff here. But I have some posts in the pipeline. Promise

It will take some time though, before I can publish as a lot of things are happening.

uhm ...

I'll see you soon, I hope.

Monday, May 31, 2010

What do you get from Twitter?

.. because I don't get it

Well Lynsheila, Thanks for your question:

"Rob, what do you get from Twitter? l must be a technophobe because l dont get it, l prefer chatting face to face"
A good question

Free twitter badgeImage via Wikipedia

Well, Twitter is quite a lot and that makes it hard to grasp and hard to explain:

  • It's some sort of chat, although mostly public, eventhough you can go private
  • It's also a form of a news reader, nowadays I get more news through Twitter than through RSS feeds
  • It's blazingly fast when something happens anywhere around the world
  • I get updates from friends and see what they are up to
  • I get insight into the lifes and thoughts of famous people (sport stars, music stars etc) so they almost appear human
  • and so much more

It has to do with information flow in all sorts of ways that you can easily subscribe to and after some time you can abondan them as easy as that.

I hear and listen and also speak out through Twitter. So that is what Twitter is to me.

So, what is Twitter to you?

I dare you, come up with your explanation to Lynsheila and all the others who don't get it, but want to get it.

Reblog this post [with Zemanta]

Friday, May 21, 2010

More amazing news from Google I/O 2010

.. and some things I want

Yesterday, 21 May 2010, there was more interesting news from the Google I/O conference. Again I wish I had been there, especially since they were given away HTC EVO to each and every conference attendee. Accept to Google employees. Too bad for Matt!

Google's Matt Cutts @ PubCon 2009Image by Andy-Beal via Flickr

I should start looking for sponsors for the Google I/O 2011 ...

Maybe the big announcements were to be expected and have been predicted, still I think these again to be great news. Also I am seriously considering getting my hands on these in the near future.

Update to Android

Release 2.2 of Android, codename Froyo, is coming. It has better performance and was demonstrated too a very enthousiastic crowd.

Improvements in various areas have been made.

  • The speed has been boosted 2 to 5 times by incorporating a Just In Time (JIT) compiler.
  • It has enterprise friendly enhancements, think Microsoft Exchange.
  • Extra APIs: Application Data Backup API and a Cloud-to-Device API.
  • Tethering and Portable Hotspot, work on your laptop in connection with your mobile phone.
  • The browser has been boosted by incorporating the V8 engine. Javascript performance boosted 2 to 3 times.

My contract for my mobile phone is coming up for renewal, but I seriously consider jumping in on the Android train. It seems to be picking up more and more speed.

Google TV

Google TV is about using that little laptop screen to watching movies and your laptop and not on that beautiful great widescreen TV you have mounted on the wall. But also about browsing the web on that TV but with limited interface.

Last year I treated my family and myself on a wonderful Philips Ambi-light flatscreen HD TV. It came with Net TV. A very limited browser on the TV. There are a load of web sites pre loaded and easily chosen, but these are all put there by Philips. The companies behind the sites are paying Philips. I, as the owner of the TV, have no way of putting my own choices up there. I can choose some favorites from the available options, but that's it.

Youtube is there but typing in a search query on the remote is going back to text again and there is no way to hookup a wireless keyboard. All in all this Net TV is just not what it should be. I may have used it ten times in ten months.

Google TV brings the web to your TV, no it makes it part of your TV experience. You watch a football match on a TV channel and can have a Twitter stream in the top right corner or something. Also it promises to make the interaction with the Web much easier. Google TV can be built in into the TV or a separate box.

As my Philips receives software updates every month or so I just hope that the learn from this announcement and improve their Net TV software in my TV. I doubt it will come close to Google TV. But I have no doubts that in teh near future we will see more and more TV sets coming with better and better internet capabilities. May it be Google TV or not.

Eventhough I do try to limit the amount of boxes in my living room the day that a Google TV box comes in could be coming sooner than later.

It's over now for this year

Luckily it's only a two day event and that means not another day of big announcements. But these are only the big announcements and more smaller announcements have been made that may have more or less impact on you depending on your occupation and interests.

Now it's time to get back to work and let the dust settle and see what other competitors will come up with and how much of these things really gonna do what they look like doing.

Reblog this post [with Zemanta]

Thursday, May 20, 2010

Google I/O 2010 is amazing

.. eventhough I am not there

Since yesterday, 19 May 2010, Google I/O is raging. Many great stuff is being published and it is hard, no impossible to keep up. It's already impossible to even try to list all the new things coming soon or are even here today already.

2008 Google I/O in USA, the Keynote.Image via Wikipedia

I'll try to name some of the more interesting things I have picked up so far.

Google Font Directory

Ever wanted to use different fonts on your site than the limited few. Mo more mandatory Times New Roman or Arial or Courier. There were already some services out there (like TypeKit) that gave you the opportunity to use the new Web Fonts, but now Google has weighed in on that and partners with TypeKit and offers a first small set of Open Source fonts to use on your web site projects.

I know I will dive into this in the very near future.

As a matter of fact I already have ;-)

The VP8 codec

HTML5 has the <video> tag. That's nothing new. But most video now being served on is now in the format of H.264, a format that has an uncertain licensing model. A model that reminds of the old Compuserve GIF licensing model. After acquiring ON2 Google now has open sourced the VP8 codec.

Already the major browsers are backing that up and also Adobe promised to release VP8 support within Flash. That should be available to more than a billion users within the next 12 months.

Adobe also showed some of the new HTML5 tools for Dreamweaver. Making it clear to developers that Adobe not only stands for Flash (and Photoshop) but also for more cutting edge web based development. Good for Adobe.

Google Storage for Developers

With Google Storage for Developers the company from Mountain View is taking on cloud services like Amazon S3. Now only for developers from the US and invitation only. But soon it can become huge with the power of the giant behind it. I expect that some great applications will begin to popup in the next year based on Google Storage.

And more is still to come.

The consequences of these three major announcements will become apparent soon enough. Expect some more announcements in the coming days of Google I/O.

It's just too much information for now!

Reblog this post [with Zemanta]

Friday, May 07, 2010

On jQuery templating

.. isn't it just shifting functionality around?

Eventhough jQuery templating is a pretty interesting concept and I feel tempted to use it, I can not stop thinking that it does not help to simplify my code.

I develop in ASP.NET mainly and do construct all the controls by hand, meaning that I first decide what my HTML will look like and then let the control render exactly that markup.

All right, all right

Arguably, I can do that with jQuery templating equally well. But I will be forced to rebuild the ViewState principle of ASP.NET in order to make changes come back to the server. I must call web services to get the data. Meaning that for each form I must have a specific web service. That is quite a bit of work.

Also I would be doing a lot of coding in JavaScript and in C# and I ike to keep as much functionality as possible in my main development language. Just to avoid confusion.

Concluding

Then again, I may have missed some stuff and maybe things can be done that I do not see yet. It's still early in the jQuery templating model and things are bound to change. I will wait and see what comes up next in this area.
For now, I will stick with my MVC inspired, Mediator based framework.

In reference to: A few thoughts on jQuery templating with jQuery.tmpl | Encosia (view on Google Sidewiki)

Reblog this post [with Zemanta]

Tuesday, April 20, 2010

IIS7 Url Rewrite Extension explained

.. for once and for all

In this great article by Scott Guthrie it is completely clear how the URL Rewrite Extension works and can be configured.

Scott Guthrie in 2007.Image via Wikipedia

Sometimes things can be pretty easy.

Solving SEO problems along the way

The SEO problems he resolves with this extension are present on most sites and even if you do not use IIS7 it is clear what these problems are and how they can be resolved.

In reference to: Tip/Trick: Fix Common SEO Problems Using the URL Rewrite Extension - ScottGu's Blog (view on Google Sidewiki)

Reblog this post [with Zemanta]

Tuesday, April 06, 2010

Another HTML5 vs Silverlight or Flash battle

.. and another one biased

I think this is one of the other over the top reactions in the HTML5 vs Silverlight or Flash or whatever you like.

A graphical despiction of a very simple html d...Image via Wikipedia

I do like Silverlight

Just to start out with one clear statement: I like Silverlight a lot and do think that many solutions can be build with it. It do has its place in my toolbox, but also has its limitations. Just saying iPad and (non WP7) smartphones.

HTML5 has its limitations as well, but also extends its reach into areas that Silverlight can not get to (iPad & (non WP7) smartphones).

It is not a simple "HTML5 vs Silverlight or Flash" battle. It's picking the right technology for the right audience.

But ..

Then onto some things that feel wrong in your article:

About the speed of implementation / ratification of standards. That has quote a bit to do with browser builders implementing rules. We all know that one browser has slowed down progress considerably in applying standards. They are still playing catch up, but with increasing speed.

The HTML5 standard is evolving at high speed and implementation across various browsers is equally swift. That in return brings the HTML5 standard quicker to a real Standard.

Some remarks about webcam / microphone control, fonts are not correct. Webcam support is in the works and webfonts are already in most browsers, although implementations differ.

Another thing to say about "standards" Silverlight is hardly a standard. Version 4 is now on the brink of release and it has only been a very short period since version 1 was out. Sounds a bit like progressive evolution, much like HTML5 is evolving.

Admittedly ..

The lack of tools for HTML5 development might a problem and I think this is an opportunity for tools developers (Adobe?) and I just wonder if Microsoft will jump into this void.

Finally, no COM support is just a blessing. HTML5 is platform independent and this can never be a veritable demand for a web based platform.

Wrapping up

At present I think Silverlight is not yet final (I have bumped my head in version 3 already and no doubt will do so in version 4) as is HTML5. I think there are use case scenarios for both and it depends on the scenario to which tool in my toolbox I will grab.

A reaction on: HTML 5 is Born Old - Quake in HTML 5 Example ( found through Google Sidewiki)

Reblog this post [with Zemanta]

Wednesday, March 31, 2010

For Web developers with a front end inkling

... ASP.NET 4 holds a lot of promise.

Finally we get control over all the horrible IDs rendered in html and styling those will become much easier.

Getting rid of the ugly and unneeded tables in some controls is here for more control over the controls.

Thank you .NET 4.0!

Image representing Scott Guthrie as depicted i...Image by Wikipedia via CrunchBase

In reference to: Cleaner HTML Markup with ASP.NET 4 Web Forms - Client IDs (VS 2010 and .NET 4.0 Series) - ScottGu's Blog (brought to you through Google Sidewiki)

Reblog this post [with Zemanta]

Tuesday, March 30, 2010

Zombies?

.. I ain't not afraid of no ghosts

While happily coding about the other day I hit Shift-F5 in Visual Studio and was greeted by the following dialog box:

Uh?

Get the gun and blow their brains out!

Well, I didn't. Just clicking the button made it go away. But I am on full alert now. But maybe I should visit this guy ...

LONDON, ENGLAND - JANUARY 11:  Canon David Par...Image by Getty Images via Daylife

Reblog this post [with Zemanta]

Thursday, March 18, 2010

Writing this HTML5 vs Silverlight post

... vice versa could be easy

I think that the writer is on a wrong track here as he is comparing two completely different things.

A new and fast rising standard for HTML and a browser plugin. The first being implemented across multiple platforms in rapid pace. The second being upgraded every 9 months and available on not all platforms.

Mind you I think both of these have huge possibilities and can do things that the others may not yet can do. I think they both have their unique use cases, but in most cases they have much overlap in possibilities.

Which one to choose depends on the situation and the market one is aiming for.

The article could have been a lot more subtle and a lot more realistic.

Refers to: http://www.silverlighthack.com/post/2010/02/08/Top-Reasons-why-HTML-5-is-not-ready-to-replace-Silverlight.aspx (through Google Sidewiki)

Reblog this post [with Zemanta]

Thursday, March 11, 2010

Google Streetview has now covered The Netherlands

.. including my car

As I blogged earlier: Google Streetview was extending it's reach across my beautiful country. I also noted that some parts were still MIA.

That has changed now.

HANNOVER, GERMANY - MARCH 03:  People gather i...Image by Getty Images via Daylife

Netherlands are covered

Now one can go across the country in Streetview and see almost any street there is. It is great fun to look at your own house, but you can now also see what that place looks like where you are going for the first time.

Reblog this post [with Zemanta]

Thursday, March 04, 2010

Trouble with Team System workspace in VS2005

.. but I solved it

I have been developing in Visual Studio 2008 lately and the chances are reasonable that I will move to Visual Studio 2010 soon. However, in my current project I needed to create a SSIS thingy to do some clever data import. Since the database we are using is SQL Server 2005 I had to do a step down to Visual Studio 2005. Not a big problem since it's still installed on my machine.

Team System

Small problem was that we are using Team System for souce code control and work item management. That's a no brainer. Just download and install the Team Explorer for Visual Studio 2005.

Well easily done and away we go.

Login into the server and away we go!

Just a quick plug here. I am using an online hosted version of Team Foundation Server. It's provided by Online-TFS and works like a breeze. In a recent outsourcing job I had to work with a TFS instance hosted on the same internal network and that wasn't anywhere close in performance as this online version!

It may seem pricy at first, but I can access it from anywhere on the Internet and still have great performance.

After starting VS2005 I just had to logon and away I went. I quickly had the Team Explorer on screen and then I just wanted to hook up to the correct Workspace to start uploading the first version of SSIS project.

That's when things went a bit wrong. I had no options in the Source Control Explorer window. I could browse to the folders on TFS but couldn't add or get anything.

I was a bit stumped.

So I did search and found some stuff on MSDN about the File - Source Control menu. But that only showed Visual SourceSafe. Ugh!

I looked a little further and decided to go through the Options dialog where a lot of the hidden gems can be found.

The solution

Going through the good old Tools - Options menu I brought up the Options dialog. And there it was hiding under the Source Control item.

I just had to pick the right plugin from the box to get going.

While there I had a quick look at the other options to see if they suited me way of life and then clicked OK.

That's it

So then I could get cracking with the mysterious ForEach Loop Container.

Reblog this post [with Zemanta]

Friday, January 22, 2010

Porting a framework to Silverlight

.. a journey getting to the contents

The last time I have been getting familiar with Silverlight. As a .NET developer with a big focus on the web I am interested in the possibilities of this plugin. (Eventhough, I also keep a close eye on the interesting stuff around HTML5.)

The Microsoft Silverlight stack, vectorization...Image via Wikipedia

I always wanted to add a little more to web applications and sites that are maybe possible using clever Javascript, but are probably easier to achieve using a plugin like Flash. Being quite fluent in .NET and C# and reasonably agile in Javascript I didn't want to learn yet another language and different IDE. So, when Silverlight came on stage I was immediatelly interested. I could be using the familiar Visual Studio, familiar C#, familiar (though slightly limited implementation of) .NET framework to do some exciting new stuff. XAML came in as a new aspect, but that was already part of the WPF stuff, so not completely new. Expression Blend to create all sorts of horrible interfaces and well, the sky is not even the limit anymore.

After some useless experimentation (extending "Hello world!") I decided to stop right there and drop everything and make a good start right from the beginning. Fundamentals first.

A framework

Within our company we use a clever framework that implements the MVC pattern. We use the same framework for Windows Forms application and ASP.NET applications. By completely separating the View logic from the Model and Controller (as it should be done) we can use the same Model and Controller logic in both types of applications.

The framework has a Mediator and all functionality is handled through that using Commands. All View controls are registered with the Mediator and are signalled to update the view when "things" change in the Model. The controls then update themselves and show or hide bits of themselves.

At first there was a bit of getting used to this way of programming, but now it strikes me again and again how little code is needed to implement logic.

All logic is handled in commands. When a button is clicked the Mediator is called to execute a command with some optional parameters. These Commands are implemented in various classes and are decorated with a Command attribute and implement an ICommand interface. The ICommand interface makes that the methods that a Command needs are implemented. The Command also has access the Model through ApplicationData object. I made a SilverlightApplicationData type with some small changes to the WebApplicationData type. For instance in the WebApplicationData we grab the buildnumber from the Web.Config and there is no such thing in Silverlight, so it is dropped for this first implementation.

Anyway, just add the attribute and we are good to go.

[Command("COMMANDNAME")]

The code the ICommand interface has among others a Do() method that can be called by the Mediator. A typical Button Click EventHandler is really simple.

Mediator.Execute("COMMANDNAME", "string parameter");

Or ..

Mediator.Execute("COMMANDNAME", "string parameter", intParameter, someOtherClassParameter);

Every parameter after the command name is passed to the actual Command as argument for its constructor.

The Mediator then executes the Command. However, the framework doesn't know which Commands will be implemented. Neither do I. What is needed is a Dictionary with all available Commands.

Dictionary<string, Command> commands

How to can the framework know which commands there are? Do we need to maintain a list in a config file? A bit nasty really. But the backbone of .NET Framework comes to the rescue: Relfection.

Reflection

Using reflection we can iterate all application assemblies and scan all types and make a Dictionary with all types that have the Command attribute. These can then be stored in the Dictionary.

Sounds easy, but is it?

Windows and web is simple

For Windows and Web applications iterating the assemblies is quite simple. We just look at the content of the Bin folder and load all *.dll (and *.exe) files. Then using reflection we scan all Types for the Command attribute. When found we add them to the Dictionary.

            foreach (string file in Directory.GetFiles( path, searchPattern, SearchOption.AllDirectories ))
            {
                Assembly assembly = Assembly.LoadFrom( file );
                Type[] types = assembly.GetTypes();
                foreach (Type type in types)
                {
                    object[] attr = type.GetCustomAttributes(typeof(CommandAttribute), false);
                    if (attr.Length == 1)
                    {
                        CommandAttribute attribute = (CommandAttribute)attr[0];
                        Command command = (Command)assembly.CreateInstance( type.FullName );
                        commands.Add( attribute.CommandName, command );
                    }
                }
            }

This is all done in a static CommandManager so we only need to scan the files once.

Silverlight is slightly different

With Silverlight the situation is a bit more complicated. There is no Bin folder that can be scanned. There is a ClientBin folder, but that's on the web server and even then the files are inside the Xap file!

Inside that renamed Zip file we find the assemblies and AppManifest.xaml file in which these files are listed. Well how do we get there?

Doing quite a bit of Googling I finally got on the right track. The above code sample needs quite a bit of rework. Whe need to do a number things:

  1. Open the Xap file
  2. Read the AppManifest.xaml.
  3. Parse the names of the assemblies
  4. Load the assemblies from the Xap file

Eventhough the Silverlight application is downloaded by the browser to the client computer we can not really get at the Xap file directly. That's the sandboxing security model working against us. So we need a clever workaround.

Luckily there is a way to get there. We can download the file to Local Storage. Since we are on the web this happens asynchronously. Using the OpenReadCompletedEventHandler we can continue the process.

Note that we also check for the existence of the Xap file in LocalStorage, just to prevent repeated downloads when you refresh the web page.

         Uri xapUri = Application.Current.Host.Source;
         string[] parts = xapUri.AbsolutePath.Split('/');
         xapFile = parts[parts.Length - 1];  // the filename is the last part of the path

         using (IsolatedStorageFile store = IsolatedStorageFile.GetUserStoreForApplication())
         {
            // check if the file is available
            if (!store.FileExists(xapFile))
            {
               // when not available download it
               WebClient webClient = new WebClient();
               webClient.OpenReadCompleted += new OpenReadCompletedEventHandler(WebClientOpenReadCompleted);
               webClient.OpenReadAsync(new Uri(xapFile, UriKind.Relative));
            }
            else
            {
               LoadAssembliesFromIsolatedStorage();
            }
         }

When WebClient has completed download the stream is copied to IsolatedStorage

      private static void WebClientOpenReadCompleted(object sender, OpenReadCompletedEventArgs e)
      {
         using (IsolatedStorageFile storageFile = IsolatedStorageFile.GetUserStoreForApplication())
         {
            IsolatedStorageFileStream fileStream = storageFile.CreateFile(xapFile);
            WriteStream(e.Result, fileStream);
            fileStream.Close();
         }
         LoadAssembliesFromIsolatedStorage();
      }

Now the assembly processing can begin.

      private static void LoadAssembliesFromIsolatedStorage()
      {
         using (IsolatedStorageFile storageFile = IsolatedStorageFile.GetUserStoreForApplication())
         {
            IsolatedStorageFileStream fileStream = storageFile.OpenFile(xapFile, FileMode.Open, FileAccess.Read);

            // parse the AppManifest.xaml file
            Stream manifestStream = Application.GetResourceStream(new StreamResourceInfo(fileStream, "application/binary"), new Uri("AppManifest.xaml", UriKind.Relative)).Stream;
            string appManifest = new StreamReader(manifestStream).ReadToEnd();

            XElement deploymentRoot = XDocument.Parse(appManifest).Root;
            List deploymentParts = (from assemblyParts in deploymentRoot.Elements().Elements()
                                              select assemblyParts).ToList();

            // now load assemblies one by one
            foreach (XElement xElement in deploymentParts)
            {
               string source = xElement.Attribute("Source").Value;
               AssemblyPart asmPart = new AssemblyPart();
               fileStream = storageFile.OpenFile(xapFile, FileMode.Open, FileAccess.Read);
               StreamResourceInfo streamInfo = Application.GetResourceStream(new StreamResourceInfo(fileStream, "application/binary"), new Uri(source, UriKind.Relative));

               Assembly assembly = asmPart.Load(streamInfo.Stream);
               // from here the code is unchanged
               Type[] types = assembly.GetTypes();
               foreach (Type type in types)
               {
                  object[] attr = type.GetCustomAttributes(typeof(CommandAttribute), false);
                  if (attr.Length == 1)
                  {
                     CommandAttribute attribute = (CommandAttribute)attr[0];
                     Command command = (Command)assembly.CreateInstance(type.FullName);
                     commands.Add(attribute.CommandName, command);
                  }
               }
            }
         }
      }

Well, it took quite some googling around and advice from a friend to get this working, but in the end the steps are quite easy to understand.

Almost there ..

So now we have everything we need. Almost that is.

As I mentioned earlier Silverlight has a slightly limited implementation of .NET framework in the sense that not all namespaces are completely implemented in the same way. And that threw up another hurdle to take.

To create an instance of Command we use an overload of the CreateInstance method in which we can pass the parameters for the command in the args parameter.

ICommand command = (ICommand)assembly.CreateInstance( commandType.FullName, false, BindingFlags.Default, null, args, CultureInfo.InvariantCulture, null );

Unfortunately Silverlight does not have this overload. We cannot pass any parameters to the instance using CreateInstance. In effect only the default constructor is called. Why the overload is omitted in Silverlight strikes me as odd.

Yet, more research was needed to solve this problem. More Reflection was needed to find the correct constructor for the type.

         Type[] parameterTypes = new Type[args.Length];
         // Initialize a ParameterModifier with the number of parameterTypes.
         ParameterModifier parameterModifiers = new ParameterModifier(args.Length);

         for (int i = 0; i < args.Length; i++)
         {
            parameterTypes[i] = args[i].GetType();
            parameterModifiers[i] = true;
         }

         // The ParameterModifier must be passed as the single element of an array.
         ParameterModifier[] paramMods = { parameterModifiers };

         // Get the constructor that takes an integer as a parameter.
         ConstructorInfo constructorInfo = commandType.GetConstructor(BindingFlags.Instance | BindingFlags.Public, 
                                       Type.DefaultBinder, parameterTypes, paramMods);
         ICommand command = (ICommand)constructorInfo.Invoke(args);

This made it all work.

Mediator.Execute("COMMANDNAME", "string parameter");

The Mediator can now make a deep copy of the Command referenced by the name "COMMANDNAME" (using the constructor that takes string parameter) and then call that Command's Do() method to actually execute it.

A really interesting journey it was and now I can start to make something useful using this framework.

Reblog this post [with Zemanta]