-
I’ve been watching more FOSDEM videos. They are very cool. Watching in 720p is awesome.
Alan McGovern on The Evolution of MonoTorrent – By far the best bittorrent library for .net. Alan talks about the challenges of writing a library that will handle things like hundreds (if not thousands) of simultaneous socket connections, why using threads [...]
-
As a .NET programmer in my day job targeting Windows desktop applications (winforms and wpf), I don’t get to stay on top of much ASP.NET or Mono. The ASP.NET stuff I feel like I have a good enough handle on via channels I use to stay on top of .NET in general (user groups, blogs, [...]
-
Today I had to flatten a jagged array . In my case, it was a string[][] and I needed to make sure every single string contained in that jagged array was set to something (non-null and non-empty). LINQ made the flattening very easy. In fact, I ended up making a generic version that I could use to flatten any type of jagged array (assuming it's a T[][]): private static IEnumerable<T> Flatten<T>(IEnumerable<T[]> data) { return from r in data from c in r select c; } Then, checking to make sure the data was valid, was easy: var flattened = Flatten(data); bool isValid = !flattened.Any(s => String.IsNullOrEmpty(s)); You could even use method grouping and reduce the validation to: bool isValid = !flattened.Any(String.IsNullOrEmpty); Technorati Tags: .NET , LINQ , Jagged Array
-
I just accidentally found Windows 7’s built in mp3 (and presumably other metadata, exif perhaps) tag editor.
I looked for this thing for what felt like hours over the past year. Eventually I sucked it up and downloaded mp3tag, but its still nice to know that this is there for the next time.
Normally when browsing my [...]
-
With C# 4 adding some support for dynamic typing one of the first thing that I wanted to do is use it with LINQ.
I want to do this:
dynamic x; var h = from y in x where y == 1 select y.something; But I get error messages on both where and select [...]
-
Don't miss Ignite 3 . This is global Ignite week, so Ignite events are being held all over the country. Ann Arbor holds its 3rd Ignite event on Thursday, March 4 at the Ross School of Business, 701...
-
Well, that's odd. Why were the default options for Intellisense turned off when I did a fresh install of Visual Studio 2010 RC1? Technorati Tags: .NET , Visual Studio 2010 RC
-
Testing Django can be somewhat challenging. Instead of simply running a unittest module, you need to run the manage.py script in your Django app passing it the “test” parameter. This sets up a test database...
-
Martin Fowler has an excellent post on Version Control, and he almost got all of the way there, but for more than just a tiny development shop I think he missed a few important pieces.
http://martinfowler.com/bliki/VersionControlTools.html
Martin does say that Mercurial and git get most of the attention and that the choice between the two come down [...]
-
Donn Felker has a great post that explains the different uses of LINQ's ToLookup and ToDictionary . Check it out! Technorati Tags: .NET , LINQ
-
I spent all day yesterday working with VS2010 RC. (MSDN Subscribers could download late on Monday. It becomes public today). First impression: It is much faster, and more stable than the beta 2 build...
-
Its 2010 and iTunes is still slow. Windows Media Player does this 5-20 times a day: So there are no good comprehensive media library managers.
Its sad but true. I think tomorrow I’ll be going back to using foobar2000 for my audio listening. WMP12 was so so so close for me, but this issue is a [...]
-
Its not just your programming group that can’t get it right. I work in a semi-disfunctional group on contract for a client who, not matter how hard we try, doesn’t seem to listen to basic software engineering principles.
I feel a little better (and a great deal worse after thinking about it) when I see that [...]
-
This is going to be fun. It’s a bit of LINQ, a bit of academic Computer Science, and a bit of meteorology. Euler Problem 14 concerns a sequence referred to as hailstorm numbers. Hailstorm number...
-
If you need a full-featured object mapper with minimal set up, I recommend you take a look at AutoMapper on Codeplex. If you need a quick-and-dirty solution, maybe the following code could help you out. First off, why am I not using AutoMapper? At my current client, there are strict rules as to the use of open source software. There's a process in place for requesting the use of a particular open source tool, but with the red-tape of the approval process (reviews, signatures, justification, etc…), it could literally take 3 – 6 months. It's just not worth it for what I need right now. So I rolled my own. This mapper is super-simple, not very smart and may have a bug or two in it, but it works for what I need it to do and reduces a lot of hand coding. USE AT YOUR OWN RISK! It uses two simple rules to map data between two objects: If a property name and type on the source match the name and type of a destination property, the value is copied. If the user has defined a custom mapping action, use that to copy data (but rule #1 is always executed first). Let's dig into the details. First, I set up a generic class that takes in a couple of types – my source and destination types. I added a clause on the destination type that it must be 'new-able' so that I could provide a utility function that would create a destination object, map it's values from a source and return it to you. public class Mapper<TSource, TDest> where TDest : new () { } Copying Properties When copying data from a source object to a destination object, we get all public instance properties of the destination and see if they have a matching (same name and same type) property on the source. If so, we set the value on our destination object: protected virtual void CopyMatchingProperties(TSource source, TDest dest) { foreach (var destProp in typeof (TDest).GetProperties(BindingFlags.Public | BindingFlags.Instance).Where(p => p.CanWrite)) { var sourceProp = typeof (TSource).GetProperties(BindingFlags.Public | BindingFlags.Instance).Where(p => p.Name == destProp.Name && p.PropertyType == destProp.PropertyType). FirstOrDefault(); if ( sourceProp != null ) { destProp.SetValue(dest, sourceProp.GetValue(source, null ), null ); } } } Custom Transformations I want the ability to define my own transformation for special cases. This is simply a list of Action<TSource, TDest> delegates: protected readonly IList<Action<TSource, TDest>> mappings = new List<Action<TSource, TDest>>(); public virtual void AddMapping(Action<TSource, TDest> mapping) { mappings.Add(mapping); } Again, simple yet functional. Perform Mappings The last thing we need is a couple of methods to execute the actual mapping: public virtual TDest MapObject(TSource source, TDest dest) { CopyMatchingProperties(source, dest); foreach (var action in mappings) { action(source, dest); } return dest; } public virtual TDest CreateMappedObject(TSource source) { TDest dest = new TDest(); return MapObject(source, dest); } You'll see that "CreatedMappedObject" was the reason we needed to have the new-able clause on the TDest generic parameter. Usage Now let's put this into action! Given a simple domain object and view model: public class DomainObject { public string Name { get; set; } public DateTime DOB { get; set; } public int Age { get; set; } public string Address { get; set; } } public class ViewModel { public string Name { get; set; } public int Age { get; set; } } As you can see, our view model only needs the Name and Age. Our mapping code looks like this: var mapper = new Mapper<DomainObject, ViewModel>(); var viewModel = mapper.CreateMappedObject(domainObject); if the view model is created somewhere else and pre-populated with other data, we would use the MapObject method instead of creating a new instance of ViewModel: var mapper = new Mapper<DomainObject, ViewModel>(); var viewModel = InitializeViewModel(); viewModel = mapper.MapObject(domainObject, viewModel); Now let's assume we want to add the user's birth year to the view: public class ViewModel { public string Name { get; set; } public int Age { get; set; } public int BirthYear { get; set; } } Yes, we could pass along the entire date of birth, but this way the view model is getting only what it needs and doesn't need to do any additional processing to get the year: var mapper = new Mapper<DomainObject, ViewModel>(); mapper.AddMapping((source,dest) => dest.BirthYear = source.DOB.Year); var viewModel = mapper.CreateMappedObject(domainObject); To encourage re-use and centralize the setup of any custom transformations, I create a subclass of my Mapper class: public class DomainModelToViewModelMapper : Mapper<DomainObject, ViewModel> { public DomainModelToViewModelMapper() { this .AddMapping((s, d) => d.BirthYear...