Category Archives: Tips

Tips

VS11 style async wrapper for the OData async model

Using the previous post we can now write wrap all asynchronous functions written using the APM pattern into tasks. This is the preferred way to write the asynchronous code in C#5.

Here is the list of async extension wrappers for all asynchronous methods used with the OData for TFS series.

namespace DataServiceAsyncExtensions
{
    using System;
    using System.Collections.Generic;
    using System.Data.Services.Client;
    using System.Threading.Tasks;

    public static class DataServiceQueryExtensions
    {
        public static Task<IEnumerable<T>> ExecuteAsync<T>(this DataServiceQuery<T> query, object state)
        {
            return Task.Factory.FromAsync<IEnumerable<T>>(query.BeginExecute, query.EndExecute, state);
        }
    }

    public static class DataServiceContextExtensions
    {
        public static Task<IEnumerable<T>> ExecuteAsync<T>(this DataServiceContext context, DataServiceQueryContinuation<T> continuation, object state)
        {
            return Task.Factory.FromAsync<DataServiceQueryContinuation<T>, IEnumerable<T>>(context.BeginExecute<T>, context.EndExecute<T>, continuation, state);
        }

        public static Task<IEnumerable<T>> ExecuteAsync<T>(this DataServiceContext context, Uri requestUri, object state)
        {
            return Task.Factory.FromAsync<Uri, IEnumerable<T>>(context.BeginExecute<T>, context.EndExecute<T>, requestUri, state);
        }

        public static Task<DataServiceResponse> ExecuteBatchAsync(this DataServiceContext context, object state, params DataServiceRequest[] queries)
        {
            if (context == null)
                throw new ArgumentNullException("context");
            return Task.Factory.FromAsync<DataServiceResponse>(context.BeginExecuteBatch(null, state, queries), context.EndExecuteBatch);
        }

        public static Task<DataServiceStreamResponse> GetReadStreamAsync(this DataServiceContext context, object entity, DataServiceRequestArgs args, object state)
        {
            return Task.Factory.FromAsync<object, DataServiceRequestArgs, DataServiceStreamResponse>(context.BeginGetReadStream, context.EndGetReadStream, entity, args, state);
        }

        public static Task<QueryOperationResponse> LoadPropertyAsync(this DataServiceContext context, object entity, string propertyName, object state)
        {
            return Task.Factory.FromAsync<object, string, QueryOperationResponse>(context.BeginLoadProperty, context.EndLoadProperty, entity, propertyName, state);
        }

        public static Task<QueryOperationResponse> LoadPropertyAsync(this DataServiceContext context, object entity, string propertyName, DataServiceQueryContinuation continuation, object state)
        {
            return Task.Factory.FromAsync<object, string, DataServiceQueryContinuation, QueryOperationResponse>(context.BeginLoadProperty, context.EndLoadProperty, entity, propertyName, continuation, state);
        }

        public static Task<QueryOperationResponse> LoadPropertyAsync(this DataServiceContext context, object entity, string propertyName, Uri nextLinkUri, object state)
        {
            return Task.Factory.FromAsync<object, string, Uri, QueryOperationResponse>(context.BeginLoadProperty, context.EndLoadProperty, entity, propertyName, nextLinkUri, state);
        }

        public static Task<DataServiceResponse> SaveChangesAsync(this DataServiceContext context, object state)
        {
            return Task.Factory.FromAsync<DataServiceResponse>(context.BeginSaveChanges, context.EndSaveChanges, state);
        }

        public static Task<DataServiceResponse> SaveChangesAsync(this DataServiceContext context, SaveChangesOptions options, object state)
        {
            return Task.Factory.FromAsync<SaveChangesOptions, DataServiceResponse>(context.BeginSaveChanges, context.EndSaveChanges, options, state);
        }
    }
}

The code is also available on github or you can download it from the link.

Tips

Wrapping Begin/End asynchronous API into C#5 tasks

Microsoft offered programmers several different ways of dealing with the asynchronous programming since .NET 1.0. The first model was Asynchronous programming model or APM for short. The pattern is implemented with two methods named BeginOperation and EndOperation. .NET 4 introduced new pattern – Task Asynchronous Pattern and with the introduction of .NET 4.5, Microsoft added language support for language integrated asynchronous coding style. You can check the MSDN for more samples and information. I will assume that you are familiar with it and have written code using it.

You can wrap existing APM pattern into TPL pattern using the Task.Factory.FromAsync methods. For example: read more »

Tips

Caller info attributes in C# 5 are a compiler feature – they are framework agnostic

The new caller information attributes in C# 5 are excellent news for people tired of writing logging and diagnostic code or implementing INotifyPropertyChanged. You simply supply the correct attribute for the function parameters with default values and voilĂ  – you get information about the caller for free. Consider the following code:

using System;
using System.Runtime.CompilerServices;

class Program
{
    static void SayMyName([CallerMemberName] string functionName = "",
                          [CallerFilePath] string filePath = "",
                          [CallerLineNumber] int lineNumber = 0)
    {
        Console.WriteLine("{0}:{1}({2})", filePath, functionName, lineNumber);
    }

    static void Main(string[] args)
    {
        SayMyName();
    }
}

The output of this simple program is:

c:\Users\Toni\Documents\Visual Studio 11\Projects\test_console\cstest\Program.cs:Main(15)

Excellent, we have the caller’s information for free. .NET 4.5 Framework introduced the above used attributes: CallerMemberNameAttribute, CallerFilePathAttribute and CallerLineNumberAttribute. They are defined in the System.Runtime.CompilerServices namespace. This means that if you are using Visual Studio 11 and you are targeting earlier framework, you do not have those types defined in mscorlib.dll. However, even though this might make you think that you are left in the dark, this is a compiler feature which means that these attributes are nothing but a magic keywords for the compiler. They themselves do nothing!

In fact, I have compiled the above program targeting .NET 2.0 Framework, the earliest target type available in Visual Studio 11. The trick is to add the right “magic” attributes and it will work since the compiler will interpret them correctly. The full source code is rather short and you can find it as a gist at github.

I based this idea on a similar “hack” for using async in projects targeting .NET 4 on the C#5 compiler: https://gist.github.com/1961087.

Tips

Drawing the control bar for Metro-style WPF applications

So you want to build Zune like applications? Here is the recipe for adjusting the necessary stuff borrowed from an excellent blog post over at bonus bits. First, create a new WPF application project and run it. You will get something like this: read more »

Tips Windows Phone 7/8

Call TouchPanel.GetState() only once per frame

A quick tip: never call TouchPanel.GetState() more than once per frame.

If one touch location state was Pressed or Released, you might not get that state in the same frame on subsequent calls. This may mess up your logic if you have layered screens, each with its own input checking capabilities.

Development Tips

C# using statement equivalent in C++/CLI for IDisposable objects

When dealing with disposable objects, C# offers elegant and simple syntax using the using statement which disposes managed resources and simplifies the code required to perform cleanup. In other words, the necessary try-finally block can be rewritten into one simple statement. However, when using disposable managed objects in the C++/CLI code, there is no equivalent for the using block. Programmer must write the entire try-finally block, introduce new local variable and needlessly complicate the code which would otherwise be relatively clean.

TL:DR

Either declare disposable objects on the stack or use the helper wrapper class at the end of this blog post. Example:

// on the stack, automatic destructor call
Managed m; 

// long syntax, unique_ptr like syntax
using_ptr<Managed^> m2(gcnew M());

// shorter syntax, same wrapper as the above
auto m3 = make_using_ptr(gcnew M());

read more »

Tips

Range-based for-loop in VS11 Beta

One C++11 feature that didn’t made it in VS10 was range-based for-loop. Even though it wasn’t planned for VS11 release either, it is actually implemented. Even though the editor will draw red squiggles, it is not actually an error to write it (as seen on the screenshot below). The usage is fairly simple:

std::vector<int> v;
for(int i: v)
{
	std::cout << i << std::endl;
}

Hit F5 and compilation passes smoothly. The console windows displays our elements, proving that in fact it does work.

Tips

Keep controls centered on resizable form

When dealing with resizable forms, managing layout can be achieved via the Anchor and Dock properties or using a layout panel. However, sometimes the design requires that certain controls stay centered, regardless of the parent form’s size. Luckily, a simple solution exists that does not involve writing centering code and handling resizing events. read more »

Tips

Uniform resizing of multiple containers in Windows Forms

When dealing with resizable dialogs, anchoring is the best way to ensure that certain controls, like containers or data grids, stretch and resize along with with the form itself. This ensures that the user experience is enhanced when dealing with large quantities of data that are, by default designed, viewed on small window. While this design is sufficient for certain cases, in other, more business like, there are limitations that can be overcome by using different container. read more »

Tips

Google data API and OAuth: “invalid_grant” error

This extremely frustrating error can be remedied by simply re-requesting device code. You will need to authorize your app again, but at least it will work. You can also try changing the secret first, but in my case it did not work.