Showing posts with label c#. Show all posts
Showing posts with label c#. Show all posts

Thursday, June 28, 2012

Reading file content using DataReader.ReadBytes in Metro apps

The Windows.Storage.Streams.DataReader.ReadBytes method stupidly breaks with the convention of the other methods on the DataReader object, by requiring you to pass in a variable to populate, instead of instantiating a new variable and returning it.

Looking at the declaration of this method:

[MethodImpl]
void IDataReader.ReadBytes([Out] byte[] value);

we see that the value is marked with an Out attribute. Note that this is not the same as an out parameter modifier.

To have your passed in value correctly populated, you need to instantiate the byte array to pass in, using the correct capacity. The capacity is available on your reader in the UnconsumedBufferLength property.

Here's a sample of using this method:

StorageFile file = await Windows.ApplicationModel.Package.Current.InstalledLocation.GetFileAsync("[filename]");
IBuffer buffer = await FileIO.ReadBufferAsync(file);
DataReader reader = DataReader.FromBuffer(buffer);
byte[] fileContent = new byte[reader.UnconsumedBufferLength];
reader.ReadBytes(fileContent);

Thursday, June 21, 2012

Deserialising a JSON formatted string to a dynamic object in C# Metro Style Apps

I found myself looking for an easy way to deserialise Json strings to dynamic objects today. Of course there are many excellent libraries (like Json.net) that will already do this for you. The problem is that I need to do it in a Metro Style app, which can't reference regular .Net libraries.

So, what to do?

First off, Json Serialisation has been provided as a first class citizen in Metro Style apps. There's no point in doing that again. We will use the Windows.Data.Json.JsonObject class provided in WinRT. Where our paths diverge from this provided class, is that the objects are accessed in a relatively gnarly way:

JsonObject jsonObject = JsonObject.Parse(jsonString);
string myStringProperty = jsonObject["myStringPropertyName"].GetString();
double myDoubleProperty = jsonObject["myDoublePropertyName"].GetNumber();
There are different methods you call depending on the type of the value you want. This type is exposed in the ValueType property of the IJsonValue interface, which is the type of the object returned by the indexing operation. We don't necessarily like this.

What I want to do is to read my Json object like this:

dynamic jsonObject = new DynamicJsonObjectReader(jsonString);
string myStringProperty = jsonObject.myStringPropertyName;
double myDoubleProperty = jsonObject.myDoublePropertyName;
It's debatable wether we would want the property to be returned as a concrete type, or as a dynamic object, but for these purposes I want a concrete type for string, double, bool and Array, and another DynamicJsonObjectReader for JsonObject.

To accomplish this, I created an object that wraps up the built-in JsonObject class and inherits from DynamicObject. I called the object a reader, because I've only overridden the TryGetMember method. To make it writable, I would also override the TrySetMember method. This is a bit more complicated, and surplus to my needs. For Now. The ToString method will spit out the Json formatted representation, which at the moment is useful for debugging. Once TrySetMember is properly implemented, ToString would be used for serialising. Here is the code:

Update:I've added an implementation for GetDynamicMemberNames. This enables the debugger to show you all the members and their values at runtime in the watch window. Pretty handy.

using System;
using System.Dynamic;
using System.Linq;
using Windows.Data.Json;

namespace JsonSerialisation
{
    internal class DynamicJsonObjectReader : DynamicObject
    {
        private readonly JsonObject jsonObject;

        public DynamicJsonObjectReader(string jsonString)
        {
            jsonObject = JsonObject.Parse(jsonString);
        }

        private DynamicJsonObjectReader(JsonObject jsonObject)
        {
            this.jsonObject = jsonObject;
        }

        public override string ToString()
        {
            return jsonObject.Stringify();
        }

        public override IEnumerable GetDynamicMemberNames()
        {
            return jsonObject.Keys;
        }
        
        public override bool TryGetMember(GetMemberBinder binder, out object result)
        {
            IJsonValue jsonValue;
            if (!jsonObject.TryGetValue(binder.Name, out jsonValue))
            {
                // return null to avoid exception.  caller can check for null this way...
                result = null;
                return true;
            }

            result = GetValue(jsonValue);
            return true;
        }

        private object GetValue(IJsonValue jsonValue)
        {
            object result = null;
            switch (jsonValue.ValueType)
            {
                case JsonValueType.Object:
                    result = new DynamicJsonObjectReader(jsonValue.GetObject());
                    break;
                case JsonValueType.String:
                    result = jsonValue.GetString();
                    break;
                case JsonValueType.Number:
                    result = jsonValue.GetNumber();
                    break;
                case JsonValueType.Boolean:
                    result = jsonValue.GetBoolean();
                    break;
                case JsonValueType.Array:
                    result = CreateArray(jsonValue.GetArray());
                    break;
            }
            return result;
        }

        private Array CreateArray(JsonArray jsonArray)
        {
            return jsonArray.Select(GetValue).ToArray();
        }
    }
}

Sunday, May 6, 2012

COM Exception "HRESULT E_FAIL has been returned from a call to a COM component" in C# Windows 8 Metro app

I've recently been developing a few Windows 8 apps using the Consumer Preview release of Windows 8 and VS11. For the last week I've been struggling with a bug that occurred in a Windows 8 C#/XAML app.

In my app I have a Hub Page, which displays a grid with grouped items. I bind this grid to a CollectionViewSource, which takes care of this grouping for me. I also have a snapped view, which uses a ListView bound to the same CollectionViewSource. I got a ComException intermittently whenever I navigated to the page in the Snapped view. No exception would occur when navigating around in the filled view.

The exception would only be reported as a System.Runtime.InteropServices.COMException, with the message "Error HRESULT E_FAIL has been returned from a call to a COM component." and the error code -2147467259

I thought for a long time that it was a syncronisation problem on the ObservableCollection I was binding to, as I had several threads updating this collection. The problem only occurred when I was replacing items in the collection.

Eventually, the fact that it was only occurring in the snapped View, made me question what the difference was between the two. The only meaningful difference was that they never showed at the same time, and the snapped view was bound to the CollectionViewSource after the first. I remembered noticing in a different article about ObservableCollection that there could be problems binding multiple UIElements to the same collection, so this made me have another look at the XAML. My first attempt was to create a copy of the CollectionViewSource for my snapped view, and change the binding for the ListView.

It worked! I almost ran naked down the street!

I have no idea why it wouldn't work previously, but I can only speculate that the filled GridView may be taking too long to render the individual items, as the process to do so is actually quite involved in this instance. Using 2 identical CollectionViewSources is less efficient, but seems to be a sad necessity this time around.

Tuesday, February 16, 2010

Tips and tricks for writing Windows services in C#

This is not meant to be an exhaustive tutorial on writing Windows services. This is just a couple of items that I tend to forget in the time between writing services. It’d be great if it helps anyone else in the process.
  1. If you haven’t done this before, or forgot everything you’ve learned, here’s a tutorial: http://www.grinn.net/blog/dev/2008/01/windows-services-in-c-part-1.html or refer to http://msdn.microsoft.com/en-us/library/zt39148a(VS.80).aspx
  2. Put your Business Logic/BOL/code that does something in a separate assembly, or at the very least in a separate method marked public, so that you can add a gui/console application/unit test to your solution to execute this code. It saves a lot of time in debugging code.
  3. The default timer in the toolbox, System.Windows.Forms.Timer, does not work in a service. You need to use System.Timers.Timer, which can be added to the toolbox. Refer here for an explanation of why it doesn’t work (Winforms timers need a messagepump on a UI thread): http://msdn.microsoft.com/en-us/library/tb9yt5e6.aspx
  4. Remember to stop your timer while processing, and restart it afterwards.To add an installer, right click on the component view of your service, and click “Add Installer”. Don’t bother with manually adding an installer to your project.
  5. Add a setup project to your solution to install the service. Add the service’s primary output action to the install, rollback and uninstall actions. If you don’t add it to rollback, a failure after the base.Install(stateSaver) in the installer class of the service, will leave you with a service that is installed, but can’t be replaced or uninstalled by your MSI. When that happens you need to use the InstallUtil command from the command line.
  6. To use the installutil from the command line, type "C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\installutil" where is the name of the assembly of your service to install the service. Add the /u flag to uninstall the service.
  7. Use Debug.Assert(false, "Attach here to debug") to have your service pop up a message to which you can attach the debugger to step through your code. Not absolutely neccesary, but it makes things easier. For that matter, this can also be used when debugging installers, or anything else requiring to be paused at a certain place for attachment, before a breakpoint can be hit.
  8. Remember to log exceptions, they will not be logged automatically (maybe if you use the logging enterprise application block?). The eventlog is a good place to do this, but remember to register your source first. This is probably best done in the installer, unless you make it configurable in the service. Creating a source requires admin privileges. Here’s a how-to: http://msdn.microsoft.com/en-us/library/k00ce235.aspx
  9. Include something to stop your service after n number of concurrent failures, or to stop logging the exceptions. You don't want to fill up the eventlog with nonsense.
  10. Application settings in the config file is used as usual with Properties.Settings.Default.PropertyName
  11. The default service name can be set on the properties of the service in the component view. There are a few other useful properties here, like CanPauseAndContinue. Check it out.
  12. The account for which to run this service is set in the properties of the ProcessInstaller component in the ProjectInstaller file’s component view.
I’ll add more items to this list as I discover them, but this is all I’ve need so far to write a windows service.