C#: Type Inferences For Generic Methods

by Jon Davis 17. March 2009 12:40

C# 3.0 has a cool feature I didn’t realize existed until now. I already knew that you can create generic methods, like so:

protected static T CaseInsensitiveFindValue<T>(Dictionary<string, T> dic, string key)
{
    if (dic.ContainsKey(key)) return dic[key];
    foreach (var kvp in dic)
    {
        if (kvp.Key.ToLower() == key.ToLower()) return kvp.Value;
    }
    return default(T);
}

That goes back to 2.0. What I didn’t realize until now was that when you invoke this method, you don’t have to pass the type in as a type argument for T. The type can be inferred!

var value = CaseInsensitiveFindValue(myDictionary, myKey);

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags:

C# | Software Development

Silverlight’s AIR Equivalent Has Been Here All Along.. At Least In Windows

by Jon Davis 5. March 2009 04:02

I think I know one more reason why Microsoft hasn’t pushed an AIR equivalent for Silverlight. It’s because it already exists in lightweight form, bundled with Internet Explorer, called HTAs, or HTML Applications.

http://www.microsoft.com/technet/scriptcenter/hubs/htas.mspx

HTAs are basically HTML files, renamed to .hta. Double-clicking an HTML file renamed to .hta opens it up in a form of Internet Explorer that has no status bar, no menu, no toolbar, just the content, and it runs in a desktop-accessible security context. You can even go chromeless (no border and no titlebar on the browser window) by setting the caption setting to false in the HTA header tag.

Of course, HTA is only usable on Windows, which, to many people, makes the comparison of HTAs to Adobe AIR fairly moot. I dunno, though, I’m not entirely inclined to agree. I just like the idea of producing Windows-installable RIAs in a portable codebase of my preferred architecture. On the other hand, cross-platform deployment of rich apps is the biggest selling point for AIR.

Technically, HTA is similar to Mozilla’s Prism (formerly “Webrunner”) in the Windows environment in that it is a way of accessing web content from a desktop icon without the bulk of the browser application. However, HTA is more like AIR in that it breaks out of the Internet Explorer security sandbox (sort of) and allows you to access the desktop environment from script.

Note: The reason why I added a “(sort of)” when saying HTA breaks out of the IE security sandbox above is because it seems there is a mis-trust that goes on when accessing some web content. I tried creating an HTA that redirected (window.location.href=) to a web page that had Silverlight content. It unexpectedly popped up a new window and then the Silverlight app failed to load due to “missing files”. I then tried referencing the web page in an IFRAME, and that worked without any problems. This was strange to me. These things said, I *am* using Windows 7 / IE 8, so it might’ve been a beta quirk. Dunno, really.

HTAs aren’t “marketed” as being very sexy. I don’t know why Microsoft stopped touting HTA as something interesting as of 2005; indeed, the Scripting Center makes HTAs seem somewhat geekish. And I never hear of HTA being compared with Adobe AIR, but I suspect that’s because AIR is presented in a sexy way and HTA is not.

There are some rough corners in HTA technology to make it awkward in its competition with Adobe AIR, here’s a quick list:

  • No app installer. You have to roll your own. HTAs are easy to produce, just take an .html file and rename it to .hta (and optionally add HTA tags to the file, etc.). The problem is that, as easy as that is, it’s not feasible for an end user, who typically won’t even be able to change the file extension (it’s hidden by default).

    Microsoft’s equivalent to AIR’s easy app installation process is ClickOnce Deployment, but once you’re using ClickOnce you’re not using HTAs, you’re using full-blown Windows binaries. Microsoft needs to produce a ClickOnce Lite that allows you to install HTAs and dependency files in something like a .docx, .xap, or .baml file (like, but not equal to, and certainly not being), maybe a new .htax file extension, being a ZIP file with all the CSS, scripts, .xaps, and other dependencies that a standalone rich HTA would need.
     
  • No app uninstaller, either. No app installer means it won’t get added to Add/Remove Programs, so if you rename an .html file to .hta and manually add it to your Start menu, well, good for you. But there is no realistic end user option for you.

    I think it’s time someone created a CodePlex solution for an HTA app installer/uninstaller if one hasn’t been started already. I’d be tempted to jump in myself if HTAs were cross-platform, but oh if I only had more free time ...
      
  • Not likely much in the way of special integration with Silverlight or other runtimes. It’s IE, so it all “just works”, just like with a normal web site. I haven’t really tinkered much with AIR so I don’t know but I’d be surprised if AIR didn’t have some special integration between Flash/ActionScript and the Webkit browser host runtime, such as alternative windowing or menuing APIs not normally available in a browser.
     
  • AFAIK, no transparency. I mentioned earlier that if you turn off the caption option in the HTA header tag, you end up with a chromeless window. (I’m not sure how you can drag windows around the desktop or resize without horribly painful hacks that work around security constraints that, frankly, suck.) But even if you drop the outer border, as far as I know, you can’t have transparency. Hence, no rounded corners. I could be wrong about that.
     
  • Not many tools out there for producing HTA apps. Adobe AIR comes with a full-blown SDK. There’s also Aptana Studio which provides an IDE for creating Adobe AIR applications. HTA, however, doesn’t really provide anything outside of MSDN documentation and “good luck”.
     
    This wouldn’t much matter since HTA truly builds on web technology (like AIR). The problem is that it’s more. The HTA SDK is the Windows Script (WScript.exe) COM server, exposing desktop objects like the file system to script, and Internet Explorer itself, which offers up extra rendering and transition filters and a script runtime that supports COM objects, alternate language support (VBScript), etc.

    So what HTA needs in order to compete in the area of tools support are
    • That HTA app installer I keep whining about for not currently existing.
    • A rich Javascript API that exposes common windowing and menuing programming options in an elegant manner, and that acts as an abstraction to WScript and other common Windows ActiveX controls that are accessible to HTAs and would be used in typical HTAs.
    • A fresh XHTML markup model, none of this all-caps HTML sample code. (And please, no more VBScript samples or ‘-o-matics’ unless side-by-side with JScript.)
    • First class support for HTA application development within Visual Studio, including:
      • Window (HTML) designer with all the HTA bells and whistles bundled into the editor and properties window (if it’s not already there??)
      • Debugger (already there, fortunately)
      • HTA installer package creation projects
    • A Silverlight and/or WPF/BAML integration API so that Silverlight / BAML code (C#/VB.NET/DLR) can “speak to” the HTA environment for such things as menus, windowing, etc. to the same extent as the “rich Javascript API” I mentioned above, and then some.
    • An icon exporter/integrator. (HTAs already support desktop icons.) 
    • Rolled into the Expression suite (export a Silverlight app from Blend to a desktop app, which can be edited further with Expression Web).
    • Some look-and-feel love on the above-mentioned, currently non-existent installer.

A fella can dream, can’t he?

Now for the money question. What would be the incentive for Microsoft to produce an AIR equivalent for Silverlight? I was always tempted to believe that there was a conflict of interest in the fact that introducing Silverlight in AIR-like form on non-Windows desktops like Mac or Linux introduced a competition problem with the primary competitive advantages of WPF, which is the XAML-based GUI environment for windowed apps, and which requires Windows. One might argue that giving Silverlight a windowing platform on the Mac or on Linux makes WPF, and thus Windows, less interesting. I used to claim this, now I’m not convinced, because I’ve seen how painfully limited Silverlight is compared to WPF. WPF has the whole of .NET available at its fingertips, as well as extra features like 3D.

That said, though, if Microsoft made HTAs a competitive AIR-like product that gave Silverlight apps a windowing and install-based platform, even if it would be exclusive to Windows, the sole argument I can think of that makes an AIR equivalent for Silverlight a competitive conflict of interest for Microsoft suddenly goes away. Now Silverlight becomes a Windows-favoring technology again, something Microsoft can use to its advantage.

And yes, I’m playing devil’s advocate with that previous paragraph. Meanwhile, you still have AIR and Prism, although, no, you can’t run Silverlight on AIR (apparently there’s some kind of security lock-down on plug-ins, although one wonders how hackable this is) and I don’t think you can access desktop objects such as COM objects from within Prism or AIR, although I believe Prism claims to have scriptable access to desktop files.

Looking at the simplicity of AIR—really, there are only a few key files, notably “Adobe AIR.dll” and “webkit.dll”—it surely can’t be hard to create a new AIR for Silverlight. The more I reconsider, the more I am back in my original agreement that AIR is all about being cross-platform, and that Silverlight needs something more. And certainly, Prism is looking more and more interesting as well.

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags:

Silverlight | Software Development

Simple Dependency Mapping

by Jon Davis 19. February 2009 07:19

Here’s my idea of simple dependency mapping, without an IoC container. The idea is to drop your binaries into the bin directory, optionally (yes, optionally) name your dependencies somewhere such as in app.config / web.config, and let ‘er rip.

I still hate Castle Windsor, et al, and will never write code around it if I can avoid it.

By the way, this is just DI, not IoC. For IoC without an IoC container, I still like eventing. See my past posts:

Dependency mapping implementation example (conceptual; one can and should use better code than this):

// Scenario infers IMyService as a referenced/shared interface-only type library
// used on both the invoker and the IMyService implementor.

// Example 1:
// match on Type.FullName
IMyService myService = (IMyService)Activator.CreateInstance(
	Dependency.GetDependency<IMyService>(ConfigurationManager.AppSettings["myServiceProvider"]));
myConsumer.MyDependency = myService;

// Example 2:
// match on Type.Name case insensitively; NOTE: This is not recommended.
IMyService myOtherService = (IMyService)Activator.CreateInstance(
	Dependency.GetDependency<IMyService>(ConfigurationManager.AppSettings["myServiceProvider2"], true));
myConsumer.MyDependency = myOtherService;

// Example 3:
// Only one match? Too lazy to name it? Just take it. NOTE: This is not recommended.
IMyService whateverService = (IMyService)Activator.CreateInstance(
	Dependency.GetDependency<IMyService>());
myConsumer.MyDependency = whateverService;

Code:

using System.Reflection; //, etc...

// ...

public class Dependency
{
    public static Dictionary<Type, List<Type>> KnownServices
        = new Dictionary<Type, List<Type>>();


    /// <summary>
    /// Returns any <see cref="Type"/> in the current <see cref="AppDomain"/>
    /// that is a <typeparamref name="T">T</typeparamref>. 
    /// </summary>
    /// <typeparam name="T">The type in the <see cref="AppDomain"/> that the
    /// return <see cref="Type"/> should be or inherit.</typeparam>
    /// <returns></returns>
    public static object GetDependency<T>()
    {
        return GetDependency<T>(null);
    }

    /// <summary>
    /// Returns any <see cref="Type"/> in the current <see cref="AppDomain"/>
    /// that is a <typeparamref name="T">T</typeparamref>. 
    /// If <paramref name="by_name"/> is not <code>null</code>, only the type(s) matching
    /// the specified <paramref name="by_name"/> with the <see cref="Type.FullName"/> is returned.
    /// </summary>
    /// <typeparam name="T">The type in the <see cref="AppDomain"/> that the
    /// return <see cref="Type"/> should be or inherit.</typeparam>
    /// <param name="by_name">The type name that should match the return value(s).</param>
    /// <example>object myService = Activator.CreateInstance(GetDependency&lt;IMyService&gt;);</example>
    public static object GetDependency<T>(string by_name)
    {
        return GetDependency<T>(by_name, false);
    }

    /// <summary>
    /// Returns any <see cref="Type"/> in the current <see cref="AppDomain"/>
    /// that is a <typeparamref name="T">T</typeparamref>. 
    /// If <paramref name="by_name"/> is not <code>null</code>, only the type(s) matching
    /// the specified name will be returned.
    /// </summary>
    /// <typeparam name="T">The type in the <see cref="AppDomain"/> that the
    /// return <see cref="Type"/> should be or inherit.</typeparam>
    /// <param name="by_name">The type name that should match the return value(s).</param>
    /// <param name="short_name_case_insensitive">If true, ignores the namespace,
    /// casing, and assembly name. For example, a match on type <code>Dog</code>
    /// might return both <code>namespace_a.doG</code> and <code>NamespaceB.Dog</code>.
    /// Otherwise, a match is made only if the <see cref="Type.FullName"/> matches
    /// exactly.
    /// </param>
    /// <returns>A <see cref="Type"/>.</returns>
    /// <example>object myService = Activator.CreateInstance(GetDependency&lt;IMyService&gt;);</example>
    public static object GetDependency<T>(string by_name, bool short_name_case_insensitive)
    {
        if (by_name != null && !short_name_case_insensitive)
        {
            return Type.GetType(by_name, true);
        }
        Init<T>();
        var t_svcs = KnownServices[typeof(T)];
        if (string.IsNullOrEmpty(by_name))
        {
            if (t_svcs.Count == 0) return null;
            if (t_svcs.Count == 1) return t_svcs[0];
            return t_svcs; // more than one, return the whole list
        }
        return t_svcs.Find(t => t.Name.ToLower() == by_name.ToLower());
    }

    private static readonly Dictionary<Type, bool> Inited = new Dictionary<Type, bool>();
    private static void Init<T>()
    {
        if (Inited.ContainsKey(typeof(T)) && Inited[typeof(T)]) return;
        if (!KnownServices.ContainsKey(typeof(T)))
            KnownServices.Add(typeof(T), new List<Type>());
        var refAssemblies = new List<Assembly>(AppDomain.CurrentDomain.GetAssemblies());
        foreach (var assembly in refAssemblies)
        {
            Type[] types = assembly.GetTypes();
            foreach (var type in types)
            {
                if (type.IsClass && !type.IsAbstract &&
                    typeof(T).IsAssignableFrom(type))
                {
                    KnownServices[typeof(T)].Add(type);
                }
            }
        }
        Inited[typeof(T)] = true;
    }
}

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags:

C# | Software Development

Nine Reasons Why 8GB Is Only Just Enough (For A Professional Business Software Developer)

by Jon Davis 13. February 2009 21:29

Today I installed 8GB on my home workstation/playstation. I had 8GB lying around already from a voluntary purchase for a prior workplace (I took my RAM back and put the work-provided RAM back in before I left that job) but the brand of RAM didn’t work correctly on my home PC’s motherboard. It’s all good now though, some high quality performance RAM from OCZ and my Windows 7 system self-rating on the RAM I/O jumped from 5.9 to 7.2.

At my new job I had to request a RAM upgrade from 2GB to 4GB. (Since it’s 32-bit XP I couldn’t go any higher.) I asked about when 64-bit Windows Vista or Windows 7 would be put on the table for consideration as an option for employees, I was told “there are no plans for 64-bit”.

The same thing happened with my last short-term gig. Good God, corporate IT folks everywhere are stuck in the year 2002. I can barely function at 4GB, can’t function much at all at 2GB.

By quadrupling the performance of your employee's system, you’d effectively double the productivity of your employee; it’s like getting a new employee for free.

If you are a multi-role developer and aren’t already saturating at least 4GB of RAM you are throwing away your employer’s money, and if you are IT and not providing at least 4GB RAM to developers and actively working on adding corporate support for 64-bit for employees’ workstations you are costing the company a ton of money due to productivity loss!! I don’t know how many times I’ve seen people restart their computers or sit and wait for 2 minutes for Visual Studio to come up because their machine is bogged down on a swap file. That was “typical” half a decade ago, but it’s not acceptable anymore. The same is true of hard drive space. Fast 1 Terabyte hard drives are available for less than $100 these days, there is simply no excuse. For any employee who makes more than X (say, $25,000), for Pete’s sake, throw in an extra $1000-$2000 or so more and get the employee two large (24-inch) monitors, at least 1TB hard drive(s) (ideally 4 drives in a RAID-0+1 array), 64-bit Windows Server 2008 / Windows Vista / Windows 7, a quad-core CPU, and 8 GB of some high performance (800+ GHz) RAM. It’s not that that’s another $2,000 or so to lose; it’s that just $2,000 will save you many thousands more dough. By quadrupling the performance of your employee's system, you’d effectively double the productivity of your employee; it’s like getting a new employee for free. And if you are the employee, making double of X (say, more than $50,000), and if your employer could somehow allow it (and they should, shame on them if they don’t and they won’t do it themselves), you should go out and get your own hardware upgrades. Make yourself twice as productive, and earn your pay with pride.

In a business environment, whether one is paid by the hour or salaried (already expected to work X hours a week, which is effectively loosely translated to hourly anyway), time = money. Period. This is not about developers enjoying a luxury, it’s about them saving time and employers saving money.

Note to the morons who argue “this is why developers are writing big, bloated software that suck up resources” .. Dear moron, this post is from the perspective of an actual developer’s workstation, not a mere bit-twiddling programmer—a developer, that is, who wears many hats and must not just write code but manage database details, work with project plans, document technical details, electronically collaborate with teammates, test and debug, etc., all in one sitting. Nothing in here actually recommends or even contributes to writing big, bloated software for an end user. The objective is productivity, your skills as a programmer are a separate concern. If you are producing bad, bloated code, the quality of the machine on which you wrote the code has little to nothing to contribute to that—on the contrary, a poor developer system can lead to extremely shoddy code because the time and patience required just to manage to refactor and re-test become such a huge burden. If you really want to test your code on a limited machine, you can rig VMWare / VirtualPC / VirtualBox to temporarily run with lesser RAM, etc. You shouldn’t have to punish yourself with poor productivity while you are creating the output. Such punishment is far more monetarily expensive than the cost of RAM.

I can think of a lot of reasons for 8+ GB RAM, but I’ll name a handful that matter most to me.

  1. Windows XP / Server 2003 alone takes up half a gigabyte of RAM (Vista / Server 2008 takes up double that). Scheduled tasks and other processes cause the OS to peak out at some 50+% more. Cost: 512-850MB. Subtotal @nominal: ~512MB; @peak: 850MB
  2. IIS isn’t a huge hog but it’s a big system service with a lot of responsibility. Cost: 50-150. Subtotal @nominal: ~550MB; @peak 1GB.
  3. Microsoft Office and other productivity applications should need to be used more than one at a time, as needed. For more than two decades, modern computers have supported a marvelous feature called multi-tasking. This means that if you have Outlook open, and you double-click a Microsoft Word attachment, and upon reading it you realize that you need to update your Excel spreadsheet, which in your train of thought you find yourself updating an Access database, and then you realize that these updates result in a change of product features so you need to reflect these details in your PowerPoint presentation, you should have been able to open each of these applications without missing a beat, and by the time you’re done you should be able to close all these apps in no more than one passing second per click of the [X] close button of each app. Each of these apps takes up as much as 100MB of RAM, Outlook typically even more, and Outlook is typically always open. Cost: 150-1GB. Subtotal @nominal: 700MB; @peak 2GB.
  4. Every business software developer should have his own copy of SQL Server Developer Edition. Every instance of SQL Server Developer Edition takes up a good 25MB to 150MB of RAM just for the core services, multiplied by each of the support services. Meanwhile, Visual Studio 2008 Pro and Team Edition come with SQL Server 2005 Express Edition, not 2008, so for some of us that means two installations of SQL Server Express. Both SQL Server Developer Edition and SQL Server Express Edition are ideal to have on the same machine since Express doesn’t have all the features of Developer and Developer doesn’t have the flat-file support that is available in Express. SQL Server sitting idly costs a LOT of CPU, so quad core is quite ideal. Cost: @nominal: 150MB, @peak 512MB. Subtotal @nominal: 850MB; @peak: 2.5GB. We haven’t even hit Visual Studio yet.
  5. Except in actual Database projects (not to be confused with code projects that happen to have database support), any serious developer would use SQL Server Management Studio, not Visual Studio, to access database data and to work with T-SQL tasks. This would be run alongside Visual Studio, but nonetheless as a separate application. Cost: 250MB. Subtotal @nominal: 1.1GB; @peak: 2.75GB.
  6. Visual Studio itself takes the cake. With ReSharper and other popular add-ins like PowerCommands installed, Visual Studio just started up takes up half a gig of RAM per instance. Add another 250MB for a typical medium-size solution. And if you, like me lately, work in multiple branches and find yourself having to edit several branches for different reasons, one shouldn’t have to close out of Visual Studio to open the next branch. That’s productivity thrown away. This week I was working with three branches; that’s 3 instances. Sample scenario: I’m coding away on my sandbox branch, then a bug ticket comes in and I have to edit the QA/production branch in an isolated instance of Visual Studio for a quick fix, then I get an IM from someone requesting an immediate resolution to something in the developer branch. Lucky I didn’t open a fourth instance. Eventually I can close the latter two instances down and continue with my sandbox environment. Case in point: Visual Studio costs a LOT of RAM. Cost @nominal 512MB, @peak 2.25GB. Subtotal @nominal: 1.6GB; @peak: 5GB.
  7. Your app being developed takes up RAM. This could be any amount, but don’t forget that Visual Studio instantiates independent web servers and loads up bloated binaries for debugging. If there are lots of services and support apps involved, they all stack up fast. Cost @nominal: 50MB, @peak 750MB. Subtotal @nominal: 1.65GB; @peak: 5.75GB.
  8. Internet Explorer and/or your other web browsers take up plenty of RAM. Typically 75MB for IE to be loaded, plus 10-15MB per page/tab. And if you’re anything like me, you’ll have lots and lots and LOTS of pages/tabs by the end of the day; by noon I typically end up with about four or five separate IE windows/processes, each with 5-15 tabs. (Mind you, all or at least most of them are work-related windows, such as looking up internal/corporate documents on the intranet or tracking down developer documentation such as API specs, blogs, and forum posts.) Cost @nominal: 100MB; @peak: 512MB. Subtotal @nominal: 1.75GB; @peak: 6.5GB.
  9. No software solution should go untested on as many platforms as is going to be used in production. If it’s a web site, it should be tested on IE 6, IE 7, and IE 8, as well as current version of Opera, Safari 3+, Firefox 1.5, Firefox 2, and Firefox 3+. If it’s a desktop app, it should be tested on every compatible version of the OS. If it’s a cross-platform compiled app, it should be tested on Windows, Mac, and Linux. You could have an isolated set of computers and/or QA staff to look into all these scenarios, but when it comes to company time and productivity, the developer should test first, and he should test right on his own computer. He should not have to shutdown to dual-boot. He should be using VMWare (or Virtual PC, or VirtualBox, etc). Each VMWare instance takes up the RAM and CPU of a normal system installation; I can’t comprehend why it is that some people think that a VMWare image should only take up a few GB of hard drive space and half a gig of RAM; it just doesn’t work that way. Also, in a distributed software solution with multiple servers involved, firing up multiple instances of VMWare for testing and debugging should be mandatory. Cost @nominal: 512MB; @peak: 4GB. Subtotal @nominal: 2.25GB; @peak: 10.5GB.

Total peak memory (64-bit Vista SP1 which was not accounted in #1): 11+GB!!!

Now, you could argue all day long that you can “save money” by shutting down all those “peak” processes to use less RAM rather than using so much. I’d argue all day long that you are freaking insane. The 8GB I bought for my PC cost me $130 from Dell. Buy, insert, test, save money. Don’t be stupid and wasteful. Make yourself productive.

EntitySpaces 2009 Q1 WCF Demo

by Jon Davis 25. January 2009 16:45

I created a new WCF demo for EntitySpaces, one of the most popular ORM solutions available for .NET which now comes with its own code generator (no longer relies on CodeSmith or myGeneration). The demo is bundled in the Release Candidate for v2009 Q1. (The developer version is released, trial version will be released tomorrow.) This one includes both console and Windows Forms clients, and a console-based service, for showing the barebones basics of what it takes to get EntitySpaces working with WCF. Both full proxies (EntitySpaces runtime libraries referenced on the client) and lightweight proxies/stubs (*no* EntitySpaces runtime libraries referenced on the client) are demonstrated, but the lightweight demo is currently limited to a console app.

Next on my plate will be a WPF demo for the lightweight proxies/stubs. No guarantees...

Anyway, here’s the documentation that went with the demo. It got posted on the EntitySpaces blog.

http://www.entityspaces.net/blog/2009/01/25/EntitySpaces+2009+And+WCF.aspx

Currently rated 5.0 by 1 people

  • Currently 5/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags:

C# | Cool Tools | Pet Projects | Software Development | SQL Server | WCF

XmlSerialized<T> and BinarySerialized<T>

by Jon Davis 21. January 2009 20:46

Here are a couple classes that I threw together for web services and WCF usage where the client is using the same data class library as the server. Microsoft auto-serializes stuff, but when serializing explicitly I prefer to retain an explicit type reference rather passing and manually deserializing a string or byte array. In other words, if I see a web service API return a string or byte[] as an XML or binary serialization of a complex class, I get cranky, because the client should know, without having to use external documentation, how the deserialization is type-mapped.

I'm sure there are a bunch of other uses for these, like saving an object graph to disk in two lines of code, etc. In fact, I'm also using XmlSerialized<T> to convert one compatible object type (full) to another object type (lightweight) and back again.

Being as these were indeed thrown together, I give no guarantees of anything. They worked for me.

Scenario:

// take ..
public string GetMyObject() {
	var myObject = new MyType();
	var sw = new System.IO.StringWriter();
	var serializer = new XmlSerializer(typeof(MyType));
	serializer.Serialize(sw, myObject);
	return sw.ToString();
}
// .. which is a total pain to deserialize, 
// and replace it altogether with ..
public XmlSerialized<MyType> GetMyObject() {
	return new XmlSerialized<MyType>(new MyType());
}
// which can be deserialized either manually or "automagically"
// using .Deserialize().

Usage:

 

var myObject = new MyType();
// serialize to XML
var myXmlSerializedObject = new XmlSerialized<MyType>(myObject);
// preview the serialized value
string serializedValue = myXmlSerializedObject.SerializedValue;
// create it on the client
myXmlSerializedObject = new XmlSerialized<MyType>(serializedValue);
// and deserialized back to POCO
var myObjectAgain = myXmlSerializedObject.Deserialize();

// binary-serialized and compressed (slower CPU, smaller footprint)
var myBinarySerializedObject = new BinarySerialized<MyType>(myObject, true);
byte[] binaryValue = myBinarySerializedObject.SerializedValue;
bool is_it_compressed = myBinarySerializedObject.IsCompressed;
myObjectAgain = myBinarySerializedObject.Deserialize();
// uncompressed (faster CPU, larger footprint)
var myUncompressedSerializedObject = new BinarySerialized<MyType>(myObject, false);
byte[] uncompressedBinaryValue = myUncompressedBinarySerializedObject.SerializedValue;
is_it_compressed = myBinarySerializedObject.IsCompressed;
myObjectAgain = myUncompressedBinarySerializedObject.Deserialize();

 

The classes:

 

[Serializable]
[DataContract]
public class XmlSerialized<T>
{
    public XmlSerialized() { }
    public XmlSerialized(string serializedValue)
    {
        this.SerializedValue = serializedValue;
    }
    public XmlSerialized(T value)
    {
        Stream stream = new MemoryStream();
        Serializer.Serialize(stream, value);
        stream.Seek(0, SeekOrigin.Begin);
        StreamReader sr = new StreamReader(stream);
        this.SerializedValue = sr.ReadToEnd();
        sr.Close();
        stream.Close();
    }

    [System.Xml.Serialization.XmlIgnore]
    private string _serializedValue = null;
    [System.Xml.Serialization.XmlElement]
    [DataMember]
    public string SerializedValue
    {
        get { return _serializedValue; }
        set { _serializedValue = value; }
    }

    public T Deserialize()
    {
        Stream s = new MemoryStream();
        StreamWriter sw = new StreamWriter(s);
        sw.Write(this.SerializedValue);
        sw.Flush();
        s.Seek(0, SeekOrigin.Begin);
        T value = (T)Serializer.Deserialize(s);
        return value;

    }

    private static XmlSerializer _Serializer = null;
    private static XmlSerializer Serializer
    {
        get
        {
            if (_Serializer == null) _Serializer = new XmlSerializer(typeof(T));
            return _Serializer;
        }
    }

    public virtual To_T ConvertTo<To_T>()
    {
        var toObj = new XmlSerialized<To_T>(this.SerializedValue);
        return toObj.Deserialize();
    }

    public virtual T ConvertFrom<FromT>(FromT obj)
    {
        var fromObj = new XmlSerialized<FromT>(obj);
        this.SerializedValue = fromObj.SerializedValue;
        return this.Deserialize();
    }

}

 

 

[Serializable]
[DataContract]
public class BinarySerialized<T>
{
    public bool IsCompressed { get; set; }
    public BinarySerialized(T value, bool compressed)
    {
        this.IsCompressed = compressed;
        var bf = new BinaryFormatter();
        var ms = new MemoryStream();
        bf.Serialize(ms, value);
        byte[] bytes = ms.ToArray();
        SerializedValue = compressed ? Compress(bytes) : bytes;
    }
    public BinarySerialized(T value)
        : this(value, true) {}
    public BinarySerialized(byte[] serializedValue)
    {
        this.SerializedValue = serializedValue;
    }
    public BinarySerialized() { }

    [DataMember]
    public byte[] SerializedValue { get; set; }

    public T Deserialize()
    {
        byte[] bytes = IsCompressed 
            ? Decompress(SerializedValue) 
            : SerializedValue;
        var ms = new MemoryStream(bytes);
        ms.Position = 0;
        var bf = new BinaryFormatter();
        T retval = (T)bf.Deserialize(ms);
        return retval;
    }

    protected virtual byte[] Compress(byte[] byteArray)
    {
        //Prepare for compress
        System.IO.MemoryStream ms = new System.IO.MemoryStream();
        System.IO.Compression.GZipStream sw = new System.IO.Compression.GZipStream(ms,
            System.IO.Compression.CompressionMode.Compress);

        //Compress
        sw.Write(byteArray, 0, byteArray.Length);
        sw.Flush();
        sw.Close();

        return ms.ToArray();
    }


    protected virtual byte[] Decompress(byte[] byteArray)
    {
        //Prepare for decompress
        var ms = new System.IO.MemoryStream(byteArray);
        ms.Position = 0;
        var sr = new System.IO.Compression.GZipStream(ms,
            System.IO.Compression.CompressionMode.Decompress);

        //Reset variable to collect uncompressed result
        int buffer_length = 100;
        byteArray = new byte[buffer_length];

        //Decompress
        int offset = 0;
        while (true)
        {
            if (offset + buffer_length > byteArray.Length)
            {
                byte[] newArray = new byte[offset + buffer_length];
                Array.Copy(byteArray, newArray, byteArray.Length);
                byteArray = newArray;
            }
            int rByte = sr.Read(byteArray, offset, buffer_length);
            if (rByte == 0)
            {
                byte[] retval = new byte[offset];
                Array.Copy(byteArray, retval, offset);
                byteArray = retval;
                break;
            }
            offset += rByte;
        }

        return byteArray;
    }
}

 

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags: ,

C# | Software Development

2 Corrections: LINQ *Can* Use POCO/SQL, and VB.NET *Doesn't* Suck

by Jon Davis 8. January 2009 21:17

Just a couple observations here.

1. LINQ *can* work with POCO/SQL.

A few (two or three?) posts ago, I complained that LINQ-to-SQL doesn't really "speak" SQL / ADO.NET, you're forced to use generated classes and a designer to work with the provider. Thus, if you want to avoid the designer and generated classes, you're forced to using plain old ADO.NET.

I am VERY happy to say that I need to go do more homework. LINQ-to-SQL does have POCO support, and in fact when reading this blog entry I realized that a week's worth of work on my pet project is garbage because it is exactly to detail what this blog seems to show that LINQ already designed it.

http://linqinaction.net/blogs/jwooley/archive/2008/06/11/linq-to-sql-s-support-for-poco.aspx 

Why does this matter? Because I believe that a business object should be database / provider / ORM agnostic. It should NEVER implement database code within itself, and it shouldn't even inherit an ORM library object. I would be willing to tack on attributes/markers that don't do anything except provide mapping cues for an external ORM.

But even attributes can be avoided, and in the above-linked article's case, avoiding them is suggested. (I don't agree with that, though, because some members are database-bound, sometimes they are not, sometimes they are named differently from the database table columns, etc.)  

2. VB.NET Actually Doesn't Suck

While I think the syntax of VB.NET is painful to look at, to say nothing of writing, I must say that I greatly admire the features that set it apart from C#. Before v2008 I didn't think they were enough. ("My"?! Come on! Even the Windows Vista team was smart enough to eliminate "My" verbiage from Windows. You're going the wrong way!)

But at a .NET users group meeting I attended a couple months ago, I noticed the profound value of v2008's integrated XML support. I'm not talking about just Dim xx = <myxml>..</myxml>. That in itself is incredibly impressive, no doubt. But what impresses me more is how you can bury such XML expressions in LINQ statements. Add on top of that the ASP-style templating that is supported with it; you can do this: Dim xx = <myxml><%=myXmlValue%></myxml> And even this: 

Dim xx = <myxml>
<% For Each x In y %>
    <x><%=x.stuff%></x>
<% Next %>
</myxml> 

I haven't validated that but that's what I understand it to offer. That demonstration doesn't say much until you see it in action... 

The blog link I mentioned above (under #1) has at the bottom of it a "crosspost" link, the recent article of which reminded me of this VB.NET functionality and made me realize that this really is something worth blogging about. And if I have to work with VB.NET in the future, so long as it is with .NET 3.5 / Visual Studio 2008, I shouldn't pass it up anymore. 

Currently rated 5.0 by 1 people

  • Currently 5/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags: ,

Software Development | VB.NET

People Are Killing Off Inheritance

by Jon Davis 7. January 2009 11:56

I'm noticing that, more and more lately, people are throwing out inheritance, as is demonstrated by this StackOverflow thread.

I'm still trying to concede my opinion on this. If the proponents of this attitude did not have "use delegation" up their sleeves I would say they are all either nuts or completely clueless about how good OOP can be written.

I think inheritance is a fabulous thing and in well-designed systems is even more important than interfaces, particularly in fundamental, framework scenarios like visual/UI controls, ORM, I/O base classes, and the like. It's also great for application design--three different account types, for example, each with a different subset of behavior but all sharing a lot of commonalities (all being accounts).

I imagine, however, that most of these folks have experienced the real world in team environments wherein bad OOP implementations of inheritence have resulted in unmaintainable code. In such cases, I can certainly see how interfaces, as a compromise, forces team members to stick to the testable specs rather than futz with the legacy. I most definitely cannot fathom how such environments are productive; reimplementing interface behavior everywhere just sounds atrociously bogged down, nothing gets done in such environments.

Delegation as an alternative to inheritance, however, makes sense in the area of code reuse. Compositing behavior services and providers in a composite class that implements multiple interfaces and hands off the implementations of those interfaces' members to the composite members is a great way to reuse code, should inheritence be avoided. 

A sealed composite delegation class does not, however, support is-a relationships, only behaves-like-a relationships via interfaces. Using interfaces alone, we again go back to procedural code and lose the great benefits of OOP and replace it with OBP (objects-based programming), a la COM. VB6 supported polymorphism as such, and its value stopped there. I have hardly used VB6 since C#, the true OOP language, became available to me as a Microsoft tools user.

Actually, a good persuasive article lies over here http://weblog.raganwald.com/2008/04/is-strictly-equivalent-to.html in favor of composition / decorator patterns. It's so persuasive, actually, that I personally think the C# 4.0 team should consider making composition / decorator pattern as easy to implement as inheritance.

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags: ,

Software Development

Why Windows and IIS Developers Need To Try PHP, Ruby, Python, Pure Javascript, Or Something Else

by Jon Davis 5. January 2009 05:04

I've argued frequently here before that rather than being a master of one thing, it's better to be knowledgeable of many things, expert in a few. This is not the same as being a jack-of-all-trades because one would suck at all those things, but if you're better at some things, rather than a master of one thing, you might actually be better than the master of the one thing, because your experience is diversified.

Perfect analogy...

http://www.candychang.com/design/pages/milk_and_muffin.htm

"[Trying other things makes your specialty] taste better because now you know what makes it special ... and your appeciation of [your specialty] gives you a better understanding of all the other [alternative technologies]."

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags:

Opinion | Software Development | Web Development

Cheat Sheet: From C# to iPhone

by Jon Davis 30. November 2008 20:55

I'm piecing together this cheat sheet. It's incomplete, and possibly less-than-fully-accurate in places, but I'm adding and editing as I go. If anyone who knows both C# and Obj-C has any suggestions for changes or additions please let me know.

On the left is "iPhone / Obj-C" and on the right is "C#/.NET understanding / equivalence".

Here's the Excel file (so far): iPhone_from_dotNet.xls

Click on the image to go to the full size version.

Currently rated 3.0 by 12 people

  • Currently 3/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags: , ,

C# | iPhone | iPhone | Software Development | Software Development


 

Powered by BlogEngine.NET 1.4.5.0
Theme by Mads Kristensen

About the author

Jon Davis (aka "stimpy77") has been a programmer, developer, and consultant for web and Windows software solutions professionally since 1997, with experience ranging from OS and hardware support to DHTML programming to IIS/ASP web apps to Java network programming to Visual Basic applications to C# desktop apps.
 
Software in all forms is also his sole hobby, whether playing PC games or tinkering with programming them. "I was playing Defender on the Commodore 64," he reminisces, "when I decided at the age of 12 or so that I want to be a computer programmer when I grow up."

Jon was previously employed as a senior .NET developer at a very well-known Internet services company whom you're more likely than not to have directly done business with. However, this blog and all of jondavis.net have no affiliation with, and are not representative of, his former employer in any way.

Contact Me 


Tag cloud

Calendar

<<  April 2021  >>
MoTuWeThFrSaSu
2930311234
567891011
12131415161718
19202122232425
262728293012
3456789

View posts in large calendar