Tuesday, February 24, 2009

Call a method on an object only when that object is not null

I have often wanted an operator or something that will do something like run a method on an object if that object is not null (returning a default value if it is null). An example:

string s = SomeClass.SomeMember.ToString(); 

maybe for output or something. Now this works just fine, unless SomeMember happens to be null, when this code will throw an exception. So the code has to become:

string s = SomeClass.SomeMember != null ? SomeClass.SomeMember.ToString() : ""; 

or something like that. Upon finding the ?? ‘null coalescing operator’ I thought that would do the trick, but that will only munge the ToString (say) return value to "" if it was null, not let you call members on a null reference. You could do something with a chain of ?? operators, but that looks nasty and if anything in the chain is actually a method call rather than a property access then it may be called multiple times…

I think that I have come up with something neat and simple that works.

public static TResult Try<T, TResult>(this T left, Func<T, TResult> func) { 
    return Try(left, func, default(TResult)); 
} 
 
public static TResult Try<T, TResult>(this T left, Func<T, TResult> func, TResult defaultValue) { 
    if(left != null) { 
        return func(left); 
    } else { 
        return defaultValue; 
    } 
} 

Which can be used like this:

string s = SomeClass.SomeMember.Try(m => m.ToString(), ""); 

I named it Try in reference to functions such as TryParse. Perhaps not the best choice of name, but I am pretty phenomenally bad a choosing names for things… If you use it on a null reference you will get back the default value you specify or if you don't specify one you get the default value of type of the lambda expression. This second case (not specifying the default explicitly) is more useful when the type is not nullable... It is useful for calling functions on members of a class that might be null. More than that of course though, as that is a lambda (well actually a Func<T, TResult> Generic Delegate which is most easily populated with a lambda) you can pretty much do whatever you like in there.

Now I understand that this is not for everybody and that it is not going to work in all situations. Sometimes a null return value will not always have the same meaning as the default value for that type, but if you keep this in mind to does clean up a lot of code.

Another example to illustrate:

public class DataObject { 
    public List<string> Strings; 
} 
 
DataObject myDataObject = new DataObject(); 
// int stringCount = myDataObject.Strings.Count; // *boom!*
int stringCount = myDataObject.Strings.Try(l => l.Count); 

So this does not give you all of the same information that you get from receiving the null value, but it makes some common stuff painless, like telling the user how many strings there are. I find myself hiding the null value a lot of the time anyway, converting it to "" or 0 or whatever, so there you go.

Real world ‘improvement’. This:

object obj = ExecuteScript(script);
if(obj != null) {
    return obj.ToString();
} else {
    return "";
}
Becomes this:
return ExecuteScript(script).Try(o => o.ToString(), "");

Incidentally, I really love how well the type inference works now. There is no need to specify the types when calling the function - like myDataObject.Strings.Try<string, int>(l => l.Count) - and the return type gets updated when you add or change the return type of the lambda expression. Very neat.

A little love for Windows Live Writer

Problem solved.

There was some odd “bug fixing” stuff in the blogger theme.

.post-body p {
  line-height: 1.4em;
  /* Fix bug in IE5/Win with italics in posts */
  margin: 0;
  height: 1%;
  overflow: visible;
}

This was confusing WLW a bit obviously. I just removed this (sorry no more support for IE5 *pfft*) and all is well. the problem that I thought I was going to have with the empty p tags between each paragraph that I was getting but do not get when WLW is working properly is a non problem. The actually empty tags: <p></p> are not rendered at all, only the tags that WLW was inserting: <p>&#160;</p> with that non breaking space in there were causing the blank paragraph to be given some space – and these are not generated when your CSS is okay.

So everything work as far as I can see. Looks like a real WYSIWYG editor now. I can click anywhere, I can insert lists, I can probably stop checking the mark-up like a freak…

Thanks Joe Cheng! You rock.

Sunday, February 22, 2009

Bad Xml – to accept or to reject, that is the question.

Was just reading this post which touches on accepting invalid Xml communications. And I agree.

I think it boils down to “make sure you produce good XML, but accept anything with the proviso that there may be odd behaviour if the format is not correct”. Library wise though, permissive reading is fine, but if your library produces bad XML you deserve to be stamped out. I have to say that the Microsoft Xml stuff is really pretty good. They are an option 1 library though, so don’t expect to be able to read in any old just, but they will not produce invalid Xml*.

This is the route that I have gone with all of the stuff that I have been doing lately. It is a little more complicated than that though because the data structure that I am using is created from the DTD** so I need to not only accept invalid XML but convert it into valid XML to store it.


* This is something that I have had to explain a few times… Sometimes is is difficult, sometimes people understand. Mostly I don’t bother complaining too much about receiving nasty Xml, but forcing myself to produce bad Xml because someone’s hand coded parser reacts badly to something valid in my valid Xml (namespace definition).

** Funny story. It’s their DTD, but they can’t manage to produce Xml that validates against it, and they expect values for certain elements that are not valid under it (value="" when value is an NMTOKEN). Chuckle…

WLW tag problems

After looking at this post from someone with formatting problems in WLW, I have switched WLW into editing without the template. Looks nasty, but the mark-up is nice.

Only problem is that now it does not put a blank p tag in between each paragraph. So I would go and change the template to add some margin to the end of a paragraph to get my spacing back but then that is going to stuff up all of the old posts! Ugh. I do not want to go back and edit them all again! I already did that once…

It would be nice if I could modify the tag that WLW puts in for a paragraph to include a class attribute – that way I could modify the template so it only affected these new posts… Actually, that is something that is a bit of a problem with Blogger in general – changes take effect on all old posts. E.g. if you change the time zone. Not much you can do about that though really.

Just store it for me

This is an interesting article: untitled document syndrome

In the past I was firmly in the “no, I really do want to specify where you are putting my file” camp, but increasingly I prefer to succumb to human nature and let someone else do it for me.

I still like to be able to configure the root of the storage. For example to put it into my svn working copy so I have a backup and can get at it from other machines. But once that is done, and as long as I can actually find the files somewhere should I want to, I do quite like the way iTunes (for example) just takes what you put into iTunes and stores it for you.

It would be nice if more applications did this. It might be nice if this was some king of system service that an application could use. I think a lot of my applications could benefit from this – it is certainly true that for most business users the location (or the very existence) of the actual file is of little importance, as long as they can find the work and get it back and use it. You only have to look at some people’s machines and the places they manage to get files saved to realise that most people either don’t know or don’t care that there is even a choice to make about the directory they save a file in.

Saturday, February 21, 2009

Login or Register

When you have a site that uses user accounts, say for returning customers, I really hate the common theme of having a login fields area and a register fields area.

Mainly because I can’t always remember if I am registered or not. Why not make the forms do double duty as login and registration forms? You put in your email address* and what you think is your password and hit the button. If that user exists and the password is correct, let me in. If that user exists and the password is not correct, bounce me with a message. If that user does not exist, go on to a registration page and get the rest of my details**, and keep the hash of my password so you only have to confirm it not get me to type it twice again.

Streamlined. The only thing that I can see that is wrong with this idea is that it does give away some information, namely the form tells you that a certain email address is registered on that site. However the existing registration form does that anyway so…


* I am pretty much a believer in the email address as username idea. There is never going to be a problem with your desired username being take already, and people who complain that they have too many email addresses or they change them often or whatever… pfft.

** Or better yet – don’t ask me for any more information, just to confirm the password. Oh, and make sure I can continue on with what I was doing.

Google JavaScript error AGAIN

What the hell Google? A JScript error again? Last week it was AdSense, this week it is in the Followers gadget.

I just happened to look at my blog before thinking about posting something and up pops a JScript error and then a blank blog page. Nice. Upon debugging I see the error is in this line:
google.friendconnect.container.renderUrlCanvasGadget({'id': 'gadget-canvas'})

Which look like it might be the Followers gadget. I disable it and no more error. So not too hard to get by, but what the hell is with all these scripting errors?

I think there might be some kind of problem with the QA and deployment strategy over at the big g…


[Edit] I went and put the gadget right back again, and the error does not reoccur… I can’t see that line of code anywhere at all, so I don’t know if that was not the problem or if it was fixed quickly or if adding and removing it updated the code or what… Gotta go.

Friday, February 20, 2009

Unfun things

Programmers tend to loathe writing documentation. I always have great documentation in mind while I am developing a nice solution to a problem, but it rarely gets realised. Usually the bare minimum gets done – sometimes less than that.

Another thing that is probably number two on the list of most not fun to do is error handling and logging.

I have just spent a little time cleaning up the error handling in the couple of applications that I am writing right now.

There are various components, running across various platforms – Windows and Web clients, .NET Remoting servers, Windows services, Web services, ASP.NET web sites (that are actually generated from specifications in xml files that are in turn created by a tool – one of the windows client applications). Anyway, the whole thing is getting a little too complex to hold in your head at once, and before it gets too complicated I wanted to put in a common logging component. I have wanted to do it for a while – get away from each component knowing how to ends an email or write the windows log. Now it is mostly done.

I guess the whole point of this ramble was just to say that I got myself to do something pretty unpleasant – fix up exception handling chains, move chunks of code around while deciding which of 3 similar implementations are correct, fix up dll referencing issues, test error conditions – by giving myself something a little but fun to do – write a nice class using generics to build and hold an error message (so a message can be build up as different components have more or less important problems), grow the re-usable library that I have and actually re-use it.

Wednesday, February 18, 2009

Adding text to a WLW post without screwing up the mark-up!

Finally! I have discovered a way to add text at the end or middle of a post without causing horrible nesting problems with the <p> tags.

If you just go clicking at the end of an existing paragraph, or even on it, or even clicking in a space that looks blank, it is pretty easy to end up with this kind of mess:

<p>
  <p>para1</p>
 
  <p>para2</p></p>

But now I have managed to work out how to avoid it! As an example, to add a paragraph to the end of a post:

  • Hover over the invisible box that represents the blank <p></p> that WLW sticks after each paragraph with text in it. You are looking for the North South East West arrow cursor.

  • Click to select it. You need to end up with the eight little squares in the corners and on the edges showing that the whole element is selected, not the insertion point indicating that it is trying to add text inside the element.

  • Now press the right arrow key. You should end up with the insertion point below the element you clicked on. Now you can type and the text will go into the paragraph element and pressing enter at the end will close the current paragraph, insert a blank one and start a new one. Remember also that you do need to press enter at the end of the paragraph, even the last one, to get the tag to close properly.

To insert a paragraph between two existing ones, you want to do the same thing with the invisible blank paragraph element between two with text in. When you press the right arrow it will look like you are in the next paragraph with text, but you aren’t. Once you get to the end of your paragraph and hit enter all will be well again.

I feel like I am 90% of the way to being able to use WLW without switching to the source pane all the time – which is how you bloody well should be able to use it. It is just a bit unfortunate that I have to do it by being careful where I click and type and so on.

Gmail 2.0 and scrolling in IE7

Gmail’s new version 2 interface might be a slight improvement visually, but it sure does not like Internet Explorer 7 very much.

If you use the scrollbar at all the cpu usage for iexplore.exe gets pegged to 100% for a couple of seconds. I have not looked into what it is actually doing yet – not interested enough perhaps. If you switch back to the old interface (there is a link up on the top right of the page) the problem goes away. The only hassle is that this setting is not saved, the next time you log in you are back to the regular interface.

Curiously if you scroll with the keyboard it works fine. Scrolling with the scroll wheel or the edge of the touchpad hangs it up too. Seems to be in the handling of the onScroll (or whatever) event.


[Edit] It seems to be a problem with FlashGet. Disabling the FlashGet GetFlash Class makes the problem go away. Interestingly enough FlashGet still seems to work just fine…

Remote debugging

Yesterday I had quite a bit of fun trying to get remote debugging of a web application working.

I did solve this problem a little (very short) while ago… but I forgot what I had done.

So after executing a couple (quite a few) iterations of a Modify, Compile, Deploy, TryToDebug, Uninstall loop I know what you have to do to get it working. At least if you are using a deployment project to put the files up on the server.

You have to add the debug output from any project that you want to debug into to the deployment project*.

You must make sure that those debug outputs are in the right directory in the File System configuration pane so that the TargetName will have the files going into the correct directory on the server**.

Then you can install and debug. The setup of the remote debugger is a bit complex too. Basically the way I got it to work was by adding my own domain user (I log into my machine by logging into the domain) to the Administrators group on the server, and then logged in (via mstsc /console) to the server as myself (so that user could reconnect back to my machine). Bingo.


* You can’t just copy them up to the server it seems. I don’t know what the difference is, but it just does not manage to find them. I have even tried loading the symbols from the modules window directly – if complains that the symbols are not for the same version of the dll. I have not seen what happens if you are not actually deploying with an msi – there could be trouble. It is just one of those cases where there is some mechanism there that is storing some information somewhere and when it works everything is rosy, but when it does not work it can be fairly opaque. I guess that is what comes from not technically knowing what you are doing, but we can’t all be experts on the internal workings of everything – there is just not time, and when most of the time it just automagically works there is not much point either.

** The target name for the debug output of some project types (e.g. ASP.Net Web Application) will be bin/AssemblyName.pdb so the output needs to be placed in the Web Application Folder (where they seem to go by default), whereas other types (e.g. Class Library) will just be AssemblyName.pdb so their output needs to be put into the bin folder – they won’t be there by default, they will be one level up in the Web Application Folder. If you do not get this right the debug symbols will fail to load. You can look at information about what is being loaded from where in the Modules window found in Debug > Windows > Modules when you are in debug mode.

Tuesday, February 17, 2009

Lotsa windows

I just had a weird occurrence… I was in gmail, clicked to archive a message, and it started to open a bunch of new windows with one certain address:
http://mail.google.com/mail/#..&remote_iframe_0@2&1&0&%7B%22s%22%3A%22resize_iframe%22%2C%22f%22%3A%22remote_iframe_0%22%2C%22c%22%3A0%2C%22a%22%3A%5B199%5D%2C%22t%22%3A%22r0rtgf-lsmnyy%22%7D

It got to about 20 or so before I managed to kill it with taskman.

Monday, February 16, 2009

Security.dll

I was getting a funky error when trying to call one of my WCF web service’s methods:

Unable to find an entry point named 'FreeCredentialsHandle' in DLL 'security.Dll'.

Fortunately my brain is working this morning and I remembered the last time I saw this kind of odd error. Looking in the bin directory of the web site, sure enough I see a dll called security.dll. Ruhroh… IIS kindly loads up any dlls that you ask it to, then when it tries to access the Microsoft Security.dll it seems to find your dll and routes calls into it. These entry points (normally) don’t exist hence the error.

The moral of the story is: Do not call your dll security.dll*.

I just went through the whole project and made sure that the outputs were called something useful like Company.Project.Thing.dll. You do need to restart the web server too so it will reload the (correct) Security.dll.


* Other bad names are probably things like System.dll, mscorlib.dll etc. A much better idea is to create a proper namespace for your code and make the assembly name something like the namespace – or even the whole namespace, why not? Knock yourself out.

Sunday, February 15, 2009

Reuse types in a Web Service

For some time I have trying, with no success, to get the Reuse types in referenced assemblies option to work after adding a web service reference to a project.

Finally I have found the answer: That option is not available for so called ‘legacy’ ASP.NET web services, only for WCF web services. So I just re-created my web service as a WCF service. My web service is a pretty simple one providing access to a .NET Remoting server hosted in a windows service. As such the code is pretty simple, and it was a matter of less than an hour to get it all going.

Just one small gotcha that I guess should be pretty obvious. The assembly with the types that you want to re-use must already be referenced in the project that you are adding the service reference to. I.e. it does not go and look for them. I don’t suppose it would have any way of doing that.

The only modification that I had to do was to the web service. It seems to work. I am a little surprised that I did not have to add the DataContractAttribute to the classes to use them… They are already marked Serializable and the members are XmlElements… perhaps that is why it works. I have not really tested it yet, just compiled the service and the client. I am thinking now that perhaps the data is not being passed at all. Will see tomorrow – when I am supposed to be working (rather than now, the weekend).


[Edit] I does work just fine. I wonder then what is the difference between using DataContract and just making them Serializable. I also wonder what is the benefit of using the ClientFactory rather than just using the Client object directly.


[Edit] There are, it seems, times when you do need to add the DataContractAttribute to your data classes. I just found that one class that I was using as a parameter caused an exception upon serialization:

There was an error while trying to serialize parameter http://tempuri.org/:Commands. The InnerException message was 'Type 'BSPG.Prism.Script.Table' with data contract name 'Table:http://schemas.datacontract.org/2004/07/BSPG.Prism.Script' is not expected. Add any types not known statically to the list of known types - for example, by using the KnownTypeAttribute attribute or by adding them to the list of known types passed to DataContractSerializer.'.  Please see InnerException for more details.

This class contains members whose type is also not a standard class. The class that was working only had members of standard types. Fortunately, it seems to work if you just decorate the top level class with the DataContractAttribute – no need to go and change each other class in there (this would have been quite a pain for me, as they are all generated classes). That said, it might turn out that it only works because after the first level they are all standard types… That is not necessarily true for all possible data though – this is a class hierarchy created by XSDObjectGen from a quite deeply nested DOM… We will see.

Saturday, February 14, 2009

Batteries

The battery meter on my laptop is playing up.

It seems to think the battery is always at 100%. The hours remaining displayed changed, and seems to be about correct, but the percentage is always at 100%. I am guessing that that is why it keeps shutting off with no warning. Hrm.

I had other stuff to post, but I am at 100% (18 minutes) so I butter go plug in.

Wednesday, February 11, 2009

Merging Help files

This may take several minutes...

Boy you are not kidding… Why does this always take so long? And why can’t you do it in the background? I don’t need the help right now, but I would like to do something else with my machine.

Changing the console font

You can add new fonts to the list available in the cmd.exe preferences screen.

First you want to find a good mono-spaced font like Consolas and install it.

Then you need to add a new String Value to the registry under HKLM\Software\Microsoft\WindowsNT\CurrentVersion\Console\TrueTypeFont called 00* with a value of the exact font name (eg Consolas)

Something needs to happen before the font can be used, I am not sure what, but a reboot achieves it (logoff does not), so a reboot is next.

Finally, you can pop open a command prompt and change the preferences to use the new font. You might need to do this a couple of times if you use different ways of getting up a command prompt: the run command, the shortcut in accessories, or a shell extension - because of the way the system applies the preferences according to window title and not the actual executable.


* the default TrueType font is specified by 0, so the next needs to be 00, if you want to add another you can add 000 etc.

AdSense JScript error

I don’t know wether it is just IE7 or what but I do seem to be getting a lot of JScript runtime errors on lots of different sites… I have opened a few in the debugger and found them to be, for the most part strangely, coming from within jQuery…

Now the AdSense stuff on this blog has started to have an error:

The bit where it barfs is:

<script>tick('1ad')</script>

with:

Object expected

so meh, not finding the tick function. I have not changed anything, but I am beginning to wonder if it is not something that I have done to this machine. Perhaps I am just paranoid, but I do seem pretty capable of some kind of voodoo against windows installations…


[Edit] S’not just me - there are some posts on the AdSense Help forum (which has a JScript error, haha) about this already (Recent Javascript Errors in Ads, Javascript errors, JavaScript error <script>tick('1ad')</script>) but no response from Google so far...


[Edit] Silently fixed by Google. I did not keep a copy of the offending source file from this morning, but looking at the same file generated just now, they seem to have totally removed the call to tick. That function by the way ends up injected into your main page and seems to be for storing timestamps for certain actions like the first load, the first time the page is scrolled, the load time of each ad etc.) Poor form really… perhaps an explanation will surface soon.

Tuesday, February 10, 2009

Multiple selection

I was watching someone the other day trying to select a number of different files from a directory to copy somewhere else. She had about four goes at it, control clicking on each file she wanted, skipping over the ones she didn’t, then accidentally clicking without holding control somewhere and undoing all of her selections, before she gave up and copied them one at a time.

Just now I was trying to move some gmail ‘suggested contacts’ to ‘my contacts’. I had never used that interface before, but I don’t like it. You select each contact by checking its checkbox, but for some odd reason they have made clicking on the name of the contact select the checkbox also – and unfortunately deselect all of the other ones! The nice thing, usually, about a list of checkboxes is that they avoid the accidental de-selection that is so easy with the control click way of doing things…

This all has just reminded me that it would be nice to have an explorer extension that made selecting multiple files more forgiving. Maybe by altering the selected state in a more robust way. You could do undo and redo of selection, you could do add to and subtract from selection, you could keep selections or save and re-load them… you could make it usable. As it is, it is just about inevitable that someone not hugely skilled with the mouse will loose all of their selections if they are trying to select a non-trivial number of files together.

SQLServer 2005

Having failed to install SQLServer 2008 – don’t ask, I grabbed the 2005 dvd and ‘installed’ it… But the server setup could not find any of the client msi files. I looked at the directory structure on the disk and where they used to have Server and Client directories, there are now Server and Tools. I am not sure if that is the problem but I went into the Tools directory and ran the setup there. It got some way through its install, but still could not find the msi for the native client, and the ‘workstation, books online and development tools’ installer would not run. So I went spelunking in the \Tools\Setup directory and ran a few msi files by hand and now it seems to be happy.

Yay, I have my SQL Server Management Studio!

The msi installers that actually managed to do something were: \Tools\Setup\sqlncli.msi and \Tools\Setup\SqlRun_Tools.msi though there may be other stuff missing… we will see.

TortoiseSVN right drag

I did not know this: http://tortoisesvn.net/most-forgotten-feature

SVN global ignore pattern

I have just been fiddling with my global ignore pattern so I thought I would post it here (more for my future self than anything else). This modification was triggered by my having fun trying to use the same repo from two different machines where the directory structure is not identical, so the *.suo files and *.user files can cause problems. I also noticed that there were a few other odd files in the repo that I don’t really want.

[Bb]in [Oo]bj Debug Release *.suo *.user _UpgradeReport_Files UpgradeLog.XML RECYCLER Thumbs.db Desktop.ini

So a little explanation:

  • [Bb]in [Oo]bj – directories containing build files generated by studio, seems like older versions of studio create the files in all lowercase where 2008 has an initial cap and as SVN is case sensitive you unfortunately need to deal with both
  • Debug Release – directories created when building a deployment project
  • *.suo *.user – user project setting and general studio user settings files
  • _UpgradeReport_Files_ – directory containing log files and stuff created when you migrate a project from an older version of studio
  • UpgradeLog.XML – the main project migration report file
  • RECYCLER – not sure if this is still needed, but I was finding this directory sometimes gets created, I guess it is for storing deleted files… was just searching for it in the repo local copy but could not find it, oh well
  • Thumbs.db Desktop.ini – files created when you do certain things in explorer, like look at a directory of images in thumbnail view

Monday, February 09, 2009

Office Live

I have a new install of Microsoft Office Word 2007 with the Office Live plug-in installed. The Office live splash screen comes up and I was having trouble configuring it – it could not seem to deal with my Live account that had a Gmail address… anyway, that is sorted now (though all my cookies are gone in the process), but the splash screen still comes up each time. I thought it was because the sign-in process was failing, but I am all set up now and it is still showing up every time I open word.

Fortunately I have found the solution on TechNet: Get Started with Office Live.

The workaround is to create a registry key called OfficeLive under the key HKEY_CURRENT_USER\Software\Microsoft.

Group policy

I hate that the group policies specified for our domain accounts have the Internet Explorer home page locked down, and the web proxy enabled. Those settings though are just registry entries, and as there is no inherent security on registry editing, you can just go back in and edit them after login.

After some time interval though I have noticed that there must be a gpupdate or something that resets the keys to the values defined by the policy. I just wrote a quick VBScript to ensure that my preferred settings are made after login.

Set shell = WScript.CreateObject("WScript.Shell")
 
shell.RegWrite "HKCU\Software\Microsoft\Internet Explorer\Main\Start Page", "http://www.google.com.au", "REG_SZ"
shell.RegWrite "HKCU\Software\Microsoft\Internet Explorer\Main\Default_Page_URL", "http://www.google.com.au", "REG_SZ"
shell.RegWrite "HKCU\Software\Microsoft\Internet Explorer\Main\Search Bar", "http://www.google.com.au", "REG_SZ"
shell.RegWrite "HKCU\Software\Microsoft\Windows\CurrentVersion\Internet Settings\ProxyEnable", 0, "REG_DWORD"

Most of the time when I pop open IE it is to go to Google. Plus the group policy had some stupid HP news site specified, and several times over the last week their first displayed news story was some model in a state of partial undress – difficult it is when the company policy enforces a breach of company policy…

Sunday, February 08, 2009

WLW Plug-in

I just finished working on a Windows Live Writer plug-in to allow insertion of snippets. You can define templates for snippets that you can then insert into the current document from the Insert list. The snippets can be anything basically, but I will be using it to insert HTML snippets of the right format to make error message blocks, command line blocks, basically all of the little bits of mark-up that I want to re-use all of the time.

To create a new template you access the options dialog via Tools > Options > Plug-ins where you select the Snippet plug-in and click Options.

You can insert the currently selected text or the clipboard contents into the template by specifying #content# or #clipboard# somewhere in the template. You can also take the content or the clipboard if the content is blank with #contentorclipboard# or the reverse with #clipboardorcontent#.

There is no documentation (other than the info here), no installer (you just need to copy the dll file to C:\Program Files\Windows Live\Writer\Plugins), and not too many features. So hopefully not too many bugs. There are a few things that I would like to work on: A context menu to select the #content# things; Pretty up the interface a bit; Add a different mode that can ask for user input to fill in the template; An installer.

I created a Google Code project for this one too, it is wlwsnippetplugin. I think that I have put the source up properly in the SVN repository… Regardless, the source is zipped there too, as is the SnippetPlugin.dll file that you can just grab and copy to the right directory.

Enjoy!

Mark-up cleanup

I have just spent some hours going through all of my old posts and editing them in WLW to get all the mark-up nice and neat and how Blogger and WLW likes it.

I have put everything in p tags, removed all of the display oriented tags (fonts, inline classes), and fixed up the code and error message and command text blocks that I had. I think I fixed most of the quote marks and apostrophes too - mainly because WLW does it automatically and they do look pretty neat.

I guess that is all a bit anal, but I do feel clean now.

Friday, February 06, 2009

Erm… ForEach

Why did I not see this before? I was pretty sure that I looked for a ForEach function before I went off looking for Map etc… but bugger me if there isn’t an extension method on IEnumerable(Of T) that does just exactly what I want.

It’s even called ForEach!

List<thing> myList = new List<thing>();
myList.ForEach(item => item.DoSomething());

[Edit] Okay, I feel a little better now… I know why I didn’t see it before - ForEach is defined on List(Of T) and not, unfortunately, on IEnumerable(Of T) which is where I was looking for it. Perhaps next week in a spare moment I might get to try my hand at writing it.

Select method problems…

An issue that I have run into using Select as Map HOF.

The Select function is only evaluated when the returned Enumerable(Of T) is evaluated. That means that the code that I posted (which I did not test until now…) does not really do anything. I guess that means that the foreach method is probably the way to go for calling a function for each item in a list.

Thinking about this, and re-reading some information about the Map function, I come to the realisation that it is perhaps my understanding of what Map is supposed to do that is incorrect. It does say that map is for transforming the items. Perhaps what I want is another, slightly different HOF that is for operating on a list of items, i.e. calling a function for each of them, rather than for building a second list. Oh I don’t know, I will keep looking.

Windows Live Writer first paragraph problem

I was having trouble with WLW messing up the mark-up for the first paragraph when I start a new blog entry.

Once I had typed the first paragraph then pressed enter, rather than starting a new paragraph tag after the first, it inserted a new one in the first one before the text. After that the paragraphs come up in pretty much the right order, but the nesting is all wrong and not at all what you would want.

Here is an example of the mess that it manages:

<p>
  <p>Second paragraph.</p>
 
  <p></p>
Third paragraph.
 
  <p>First paragraph.</p></p>

What you want really is this:

<p>First paragraph.</p>
 
<p></p>
 
<p>Second paragraph.</p>
 
<p></p>
 
<p>Third paragraph.</p>

I have finally worked out what was causing this. It was the fact that I was clicking in the edit area before typing! So if you edit the title, you need to NOT click in the post body area, you can just hit Enter after you are done with the title and it seems to work.

Unfortunately, clicking will have bad effects on the mark-up whenever you do it in a blank area… You need to be clicking in an existing paragraph or else it seems to get a bit stuffed up. I am still trying to work out exactly which action causes which problems and hot to possibly avoid them. One is to paste in the html for a paragraph with some text in it rather than clicking at the end of a post to add a new paragraph. This is a beta product though so I guess one is meant to deal with quirkiness.

Another related note: you really have to hit Enter at the end of a paragraph, even the last one. If you don’t you can end up with:

<p>Paragraph 1.</p>
 
<p></p>
Paragraph 2.
 

I like WLW. I am sure there is not much more to go before it is kind to your mark-up. The sad thing is that this kind of stuff is probably not that important to a lot of people.

Thursday, February 05, 2009

foreach to LINQ to HOF progression

Three stages of a real world example.

protected virtual string ReplaceFunctions(string messageTemplate) {
    string messageBody = messageTemplate;
    Regex ex = new Regex(@"\$(?<name>[^\$]+)\$");
    MatchCollection functions = ex.Matches(messageTemplate);
 
    foreach(Match function in functions) {
        if(function.Groups["name"].Success) {
            messageBody = messageBody.Replace(string.Format("${0}$", function.Groups["name"].Value), "");
        }
    }
    return messageBody;
}

protected virtual string ReplaceFunctions(string messageTemplate) {
    string messageBody = messageTemplate;
    Regex ex = new Regex(@"\$(?<name>[^\$]+)\$");
    MatchCollection functions = ex.Matches(messageTemplate);
 
    foreach(var function in (from Match f in functions where f.Groups["name"].Success select f)) {
        messageBody = messageBody.Replace(string.Format("${0}$", function.Groups["name"].Value), "");
    }
 
    return messageBody;
}

protected virtual string ReplaceFunctions(string messageTemplate) {
    string messageBody = messageTemplate;
    Regex ex = new Regex(@"\$(?<name>[^\$]+)\$");
    MatchCollection functions = ex.Matches(messageTemplate);
 
    functions.OfType<Match>().Where(function => function.Groups["name"].Success).Select(function => messageBody.Replace(string.Format("${0}$", function.Groups["name"].Value), ""));
    
    return messageBody;
}

C# Map HOF goodness

The Map higher order function is provided in C# as the Select extension method.

So to cover the last step that I was going on about this morning, i.e. to transform this:

foreach(var field in (from field in TheForm.Fields where field.Disabled select field)) {
    field.DoSomething();
}

We can use method syntax (fluent) rather than query syntax to give the one liner:

TheForm.Fields.Where(field => field.Disabled).Select(field => field.DoSomething());

Neato!

Incidentally though, this seems to only work when DoSomething returns a non void. For example, if you try to compile:

TheForm.Fields.Where(field => field.Disabled).Select(field => Console.WriteLine(field.Name));

You will get an error:

The type arguments for method 'System.Linq.Enumerable.Select<TSource,TResult>(System.Collections.Generic.IEnumerable<TSource>, System.Func<TSource,TResult>)' cannot be inferred from the usage. Try specifying the type arguments explicitly.

This is pretty easy to fix though by changing the expression lambda to a statement lambda:

TheForm.Fields.Where(field => field.Disabled).Select(field => { Console.WriteLine(field.Name); return true; });

Windows Live Writer and Blogger formatting

I think I have it worked out.

There is a Blogger setting that stuffs up edits done with Live Writer. Settings > Formatting > Convert line breaks needs to be set to No. Then you don’t seem to get the double line spacing.

The trick with WLW seems to be to let it put in paragraph tags and to never ever edit the post in blogger. Or at least to never switch between the blogger html editor and the compose editor – that really screws things up.

In the end, WLW is still in beta so there are issues. Undo does not do what I would expect. You can’t just type away and press enter to get a new paragraph… Seems like for the first paragraph you have to hit enter then the down arrow otherwise the insertion point is above the first paragraph container. Odd.

I will just resign myself to being careful with the editor, then being prepared to fix the mark-up by hand.

The CodeSnippet pug-in works best if you do not embed the styles but copy them to your template to be re-used. That is how I wanted to do it anyway. Here is a little code snippet:

// Check for required fields
foreach(var f in from f in TheForm.Fields
                 where f.RequiredForEmail
                 select f) {
    prop = requestType.GetProperty(f.Name);
    if(prop == null || prop.GetValue(data, null).IsBlank()) {
        Ok = false;
        break;
    }
}

Query pattern problem

I have been getting this error with some LINQ expressions:

Could not find an implementation of the query pattern for source type 'System.Text.RegularExpressions.MatchCollection'. 'Where' not found. Consider explicitly specifying the type of the range variable 'v'

You get this error because MatchCollection implements only IEnumerable and not IEnumerable(Of T) All you need to do is change:

from v in ex.Matches(template)

to:

from Match v in ex.Matches(template)

I.e. do what it says and specify the type of the range variable.

CodeSnippet plug-in

Dammit. Those code snippets look so nice in Live Writer… grr. They get all sorts of horrible linebreaks and the formatting does not work at all. Work dammit!

Explorer:

Live Writer:

Grumble.

LINQ expression syntax

I have been recently starting to use LINQ expression syntax a little more. One refactoring that I have been doing is changing things like:

foreach(SomeItem item in items) {
    if(item.SomeProperty == someValue) {
        item.DoSomething();
    }
}

into the slightly nicer:

foreach(var item in (from i in items
                     where i.SomeProperty == someValue
                     select i)) {
    item.DoSomething();
}

… My only hesitation is the nastiness of the syntax (if you try to get it inline with no extra variable definitions – yes I know the extra parentheses are not required, but I find var item in from i in items to be very unreadable, plus I am often adding method syntax to these things at a later stage)… Some syntactic sugar might be nice to get:

foreach(var item from items                                      
                 where item.SomeProperty == someValue                 
                 select item) {
    item.DoSomething();
}

There is probably also a higher order function way to do this for simple cases of just calling one function on each match, but most of the time the code is not as simple as a single method call. Ideally I would love to do something like:

(from i in items where i.SomeProperty == someValue select i).Map(DoSomething);

P.S. Do not like the new Windows Live Writer editor. I just want an editor that makes it easy to create nice neat mark-up! Why is it so difficult to NOT put in paragraphs and other containers that I don’t need? And why can’t I see them in edit mode? And why do I drop out of the edit container and then have the backspace key delete the whole container?