Archive

Archive for the ‘C#’ Category

Limit The Number Of C# Tasks That Run In Parallel

April 17th, 2016 4 comments

Why I needed to throttle the number of Tasks running simultaneously

In the past few months I have come across the scenario where I wanted to run a whole bunch of Tasks (potentially thousands), but didn’t necessarily want to run all (or even a lot) of them in parallel at the same time. In my scenarios I was using the Tasks to make web requests; not CPU-heavy work, otherwise I would have opted for using Parellel.Foreach.

The first time I encountered this problem, it was because my application would be running on the cheapest VM that I could get from AWS; this meant a server with 1 slow CPU and less than 1GB of RAM.  Telling that server to spin up 100 threads simultaneously likely would not end very well. I realize that the OS determines how many threads to run at a time, so likely not all 100 threads would run concurrently, but having the ability to specify a lower maximum than the OS would use gives us more control over bulkheading our application to make sure it plays nice and does not consume too many server resources.

The second time, I needed to request information from one of our company’s own web services. The web service used pagination for retrieving a list of user. There was no endpoint that would give me all users in one shot; instead I had to request the users on page 1, page 2, page 3, etc. until I reached the last page. In this case, my concern was around DOSing (Denial of Service) our own web service. If I created 500 web request Tasks to retrieve the users from 500 pages and made all of the requests simultaneously, I risked putting a lot of stress on my web service, and potentially on my network as well.

In both of these cases I was looking for a solution that would still complete all of the Tasks I created, but would allow me to specify that a maximum of, say 5, should run at the same time.

 

What the code to run a bunch of Tasks typically looks like

Let’s say you have a function that you want to run a whole bunch of times concurrently in separate Tasks:

public void DoSomething(int taskNumber)
{
	Thread.Sleep(TimeSpan.FromSeconds(1));
	Console.WriteLine("Task Number: " + taskNumber);
}

Here is how you typically might start up 100 Tasks to do something:

public void DoSomethingALotWithTasks()
{
	var listOfTasks = new List<Task>();
	for (int i = 0; i < 100; i++)
	{
		var count = i;
		// Note that we start the Task here too.
		listOfTasks.Add(Task.Run(() => Something(count)));
	}
	Task.WaitAll(listOfTasks.ToArray());
}

 

What the code to run a bunch of Tasks and throttle how many are ran concurrently looks like

Here is how you would run those same tasks using the throttling function I provide further down, limiting it to running at most 3 Tasks simultaneously.

public void DoSomethingALotWithTasksThrottled()
{
	var listOfTasks = new List<Task>();
	for (int i = 0; i < 100; i++)
	{
		var count = i;
		// Note that we create the Task here, but do not start it.
		listOfTasks.Add(new Task(() => Something(count)));
	}
	Tasks.StartAndWaitAllThrottled(listOfTasks, 3);
}

 

Gimme the code to limit my concurrent Tasks!

Because I needed this solution in different projects, I created a nice generic, reusable function for it. I’m presenting the functions here, and they can also be found in my own personal open-source utility library here.

/// <summary>
/// Starts the given tasks and waits for them to complete. This will run, at most, the specified number of tasks in parallel.
/// <para>NOTE: If one of the given tasks has already been started, an exception will be thrown.</para>
/// </summary>
/// <param name="tasksToRun">The tasks to run.</param>
/// <param name="maxActionsToRunInParallel">The maximum number of tasks to run in parallel.</param>
/// <param name="cancellationToken">The cancellation token.</param>
public static void StartAndWaitAllThrottled(IEnumerable<Task> tasksToRun, int maxActionsToRunInParallel, CancellationToken cancellationToken = new CancellationToken())
{
	StartAndWaitAllThrottled(tasksToRun, maxActionsToRunInParallel, -1, cancellationToken);
}

/// <summary>
/// Starts the given tasks and waits for them to complete. This will run the specified number of tasks in parallel.
/// <para>NOTE: If a timeout is reached before the Task completes, another Task may be started, potentially running more than the specified maximum allowed.</para>
/// <para>NOTE: If one of the given tasks has already been started, an exception will be thrown.</para>
/// </summary>
/// <param name="tasksToRun">The tasks to run.</param>
/// <param name="maxActionsToRunInParallel">The maximum number of tasks to run in parallel.</param>
/// <param name="timeoutInMilliseconds">The maximum milliseconds we should allow the max tasks to run in parallel before allowing another task to start. Specify -1 to wait indefinitely.</param>
/// <param name="cancellationToken">The cancellation token.</param>
public static void StartAndWaitAllThrottled(IEnumerable<Task> tasksToRun, int maxActionsToRunInParallel, int timeoutInMilliseconds, CancellationToken cancellationToken = new CancellationToken())
{
	// Convert to a list of tasks so that we don't enumerate over it multiple times needlessly.
	var tasks = tasksToRun.ToList();

	using (var throttler = new SemaphoreSlim(maxActionsToRunInParallel))
	{
		var postTaskTasks = new List<Task>();

		// Have each task notify the throttler when it completes so that it decrements the number of tasks currently running.
		tasks.ForEach(t => postTaskTasks.Add(t.ContinueWith(tsk => throttler.Release())));

		// Start running each task.
		foreach (var task in tasks)
		{
			// Increment the number of tasks currently running and wait if too many are running.
			throttler.Wait(timeoutInMilliseconds, cancellationToken);

			cancellationToken.ThrowIfCancellationRequested();
			task.Start();
		}

		// Wait for all of the provided tasks to complete.
		// We wait on the list of "post" tasks instead of the original tasks, otherwise there is a potential race condition where the throttler&#39;s using block is exited before some Tasks have had their "post" action completed, which references the throttler, resulting in an exception due to accessing a disposed object.
		Task.WaitAll(postTaskTasks.ToArray(), cancellationToken);
	}
}

Above I have them defined as static functions on my own Tasks class, but you can define them however you like. Notice that the functions also Start the Tasks, so you should not start them before passing them into these functions, otherwise an exception will be thrown when it tries to restart a Task. The last thing to note is you will need to include the System.Threading and System.Threading.Tasks namespaces.

Here are the async equivalents of the above functions, to make it easy to not block the UI thread while waiting for your tasks to complete:

/// <summary>
/// Starts the given tasks and waits for them to complete. This will run, at most, the specified number of tasks in parallel.
/// <para>NOTE: If one of the given tasks has already been started, an exception will be thrown.</para>
/// </summary>
/// <param name="tasksToRun">The tasks to run.</param>
/// <param name="maxTasksToRunInParallel">The maximum number of tasks to run in parallel.</param>
/// <param name="cancellationToken">The cancellation token.</param>
public static async Task StartAndWaitAllThrottledAsync(IEnumerable<Task> tasksToRun, int maxTasksToRunInParallel, CancellationToken cancellationToken = new CancellationToken())
{
	await StartAndWaitAllThrottledAsync(tasksToRun, maxTasksToRunInParallel, -1, cancellationToken);
}

/// <summary>
/// Starts the given tasks and waits for them to complete. This will run the specified number of tasks in parallel.
/// <para>NOTE: If a timeout is reached before the Task completes, another Task may be started, potentially running more than the specified maximum allowed.</para>
/// <para>NOTE: If one of the given tasks has already been started, an exception will be thrown.</para>
/// </summary>
/// <param name="tasksToRun">The tasks to run.</param>
/// <param name="maxTasksToRunInParallel">The maximum number of tasks to run in parallel.</param>
/// <param name="timeoutInMilliseconds">The maximum milliseconds we should allow the max tasks to run in parallel before allowing another task to start. Specify -1 to wait indefinitely.</param>
/// <param name="cancellationToken">The cancellation token.</param>
public static async Task StartAndWaitAllThrottledAsync(IEnumerable<Task> tasksToRun, int maxTasksToRunInParallel, int timeoutInMilliseconds, CancellationToken cancellationToken = new CancellationToken())
{
	// Convert to a list of tasks so that we don't enumerate over it multiple times needlessly.
	var tasks = tasksToRun.ToList();

	using (var throttler = new SemaphoreSlim(maxTasksToRunInParallel))
	{
		var postTaskTasks = new List<Task>();

		// Have each task notify the throttler when it completes so that it decrements the number of tasks currently running.
		tasks.ForEach(t => postTaskTasks.Add(t.ContinueWith(tsk => throttler.Release())));

		// Start running each task.
		foreach (var task in tasks)
		{
			// Increment the number of tasks currently running and wait if too many are running.
			await throttler.WaitAsync(timeoutInMilliseconds, cancellationToken);

			cancellationToken.ThrowIfCancellationRequested();
			task.Start();
		}

		// Wait for all of the provided tasks to complete.
		// We wait on the list of "post" tasks instead of the original tasks, otherwise there is a potential race condition where the throttler&#39;s using block is exited before some Tasks have had their "post" action completed, which references the throttler, resulting in an exception due to accessing a disposed object.
		await Task.WhenAll(postTaskTasks.ToArray());
	}
}

<Update date=2016-04-29>

Shortly after publishing this post I discovered Parallel.Invoke, which can also throttle the number of threads, but takes Actions as input instead of Tasks. Here’s an example of how to limit the number of threads using Parallel.Invoke:

public static void DoSomethingALotWithActionsThrottled()
{
	var listOfActions = new List<Action>();
	for (int i = 0; i < 100; i++)
	{
		var count = i;
		// Note that we create the Action here, but do not start it.
		listOfActions.Add(() => DoSomething(count));
	}

	var options = new ParallelOptions {MaxDegreeOfParallelism = 3};
	Parallel.Invoke(options, listOfActions.ToArray());
}

Notice that you define the max number of threads to run simultaneously by using the ParallelOptions classes MaxDegreeOfParallelism property, which also accepts a CancellationToken if needed. This method is nice because it doesn’t require having the additional custom code; it’s all built into .Net. However, it does mean dealing with Actions instead of Tasks, which isn’t a bad thing at all, but you may have a personal preference of which one you prefer to work with. Also, Tasks can offer additional functionality, such as ContinueWith(), and Parallel.Invoke does not provide an asynchronous version, but my functions do. According to this MSDN page, Parallel.Invoke uses Task.WaitAll() under the hood, so they should be equivalent performance-wise, and there shouldn’t be any situations where using one is preferable over the other. This other MSDN page goes into detail about Tasks, and also mentions using Parallel.Invoke near the start.

</Update>

And if you don’t believe me that this works, you can take a look at this sample project and run the code for yourself.

I hope you find this information useful. Happy coding!

Saving And Loading A C# Object’s Data To An Xml, Json, Or Binary File

March 14th, 2014 16 comments

I love creating tools, particularly ones for myself and other developers to use.  A common situation that I run into is needing to save the user’s settings to a file so that I can load them up the next time the tool is ran.  I find that the easiest way to accomplish this is to create a Settings class to hold all of the user’s settings, and then use serialization to save and load the class instance to/from a file.  I mention a Settings class here, but you can use this technique to save any object (or list of objects) to a file.

There are tons of different formats that you may want to save your object instances as, but the big three are Binary, XML, and Json.  Each of these formats have their pros and cons, which I won’t go into.  Below I present functions that can be used to save and load any object instance to / from a file, as well as the different aspects to be aware of when using each method.

The follow code (without examples of how to use it) is also available here, and can be used directly from my NuGet Package.

 

Writing and Reading an object to / from a Binary file

  • Writes and reads ALL object properties and variables to / from the file (i.e. public, protected, internal, and private).
  • The data saved to the file is not human readable, and thus cannot be edited outside of your application.
  • Have to decorate class (and all classes that it contains) with a [Serializable] attribute.
  • Use the [NonSerialized] attribute to exclude a variable from being written to the file; there is no way to prevent an auto-property from being serialized besides making it use a backing variable and putting the [NonSerialized] attribute on that.
/// <summary>
/// Functions for performing common binary Serialization operations.
/// <para>All properties and variables will be serialized.</para>
/// <para>Object type (and all child types) must be decorated with the [Serializable] attribute.</para>
/// <para>To prevent a variable from being serialized, decorate it with the [NonSerialized] attribute; cannot be applied to properties.</para>
/// </summary>
public static class BinarySerialization
{
	/// <summary>
	/// Writes the given object instance to a binary file.
	/// <para>Object type (and all child types) must be decorated with the [Serializable] attribute.</para>
	/// <para>To prevent a variable from being serialized, decorate it with the [NonSerialized] attribute; cannot be applied to properties.</para>
	/// </summary>
	/// <typeparam name="T">The type of object being written to the XML file.</typeparam>
	/// <param name="filePath">The file path to write the object instance to.</param>
	/// <param name="objectToWrite">The object instance to write to the XML file.</param>
	/// <param name="append">If false the file will be overwritten if it already exists. If true the contents will be appended to the file.</param>
	public static void WriteToBinaryFile<T>(string filePath, T objectToWrite, bool append = false)
	{
		using (Stream stream = File.Open(filePath, append ? FileMode.Append : FileMode.Create))
		{
			var binaryFormatter = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();
			binaryFormatter.Serialize(stream, objectToWrite);
		}
	}

	/// <summary>
	/// Reads an object instance from a binary file.
	/// </summary>
	/// <typeparam name="T">The type of object to read from the XML.</typeparam>
	/// <param name="filePath">The file path to read the object instance from.</param>
	/// <returns>Returns a new instance of the object read from the binary file.</returns>
	public static T ReadFromBinaryFile<T>(string filePath)
	{
		using (Stream stream = File.Open(filePath, FileMode.Open))
		{
			var binaryFormatter = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();
			return (T)binaryFormatter.Deserialize(stream);
		}
	}
}

 

And here is an example of how to use it:

[Serializable]
public class Person
{
	public string Name { get; set; }
	public int Age = 20;
	public Address HomeAddress { get; set;}
	private string _thisWillGetWrittenToTheFileToo = "even though it is a private variable.";

	[NonSerialized]
	public string ThisWillNotBeWrittenToTheFile = "because of the [NonSerialized] attribute.";
}

[Serializable]
public class Address
{
	public string StreetAddress { get; set; }
	public string City { get; set; }
}

// And then in some function.
Person person = new Person() { Name = "Dan", Age = 30; HomeAddress = new Address() { StreetAddress = "123 My St", City = "Regina" }};
List<Person> people = GetListOfPeople();
BinarySerialization.WriteToBinaryFile<Person>("C:\person.bin", person);
BinarySerialization.WriteToBinaryFile<List<People>>("C:\people.bin", people);

// Then in some other function.
Person person = BinarySerialization.ReadFromBinaryFile<Person>("C:\person.bin");
List<Person> people = BinarySerialization.ReadFromBinaryFile<List<Person>>("C:\people.bin");

 

Writing and Reading an object to / from an XML file (Using System.Xml.Serialization.XmlSerializer in the System.Xml assembly)

  • Only writes and reads the Public properties and variables to / from the file.
  • Classes to be serialized must contain a public parameterless constructor.
  • The data saved to the file is human readable, so it can easily be edited outside of your application.
  • Use the [XmlIgnore] attribute to exclude a public property or variable from being written to the file.
/// <summary>
/// Functions for performing common XML Serialization operations.
/// <para>Only public properties and variables will be serialized.</para>
/// <para>Use the [XmlIgnore] attribute to prevent a property/variable from being serialized.</para>
/// <para>Object to be serialized must have a parameterless constructor.</para>
/// </summary>
public static class XmlSerialization
{
	/// <summary>
	/// Writes the given object instance to an XML file.
	/// <para>Only Public properties and variables will be written to the file. These can be any type though, even other classes.</para>
	/// <para>If there are public properties/variables that you do not want written to the file, decorate them with the [XmlIgnore] attribute.</para>
	/// <para>Object type must have a parameterless constructor.</para>
	/// </summary>
	/// <typeparam name="T">The type of object being written to the file.</typeparam>
	/// <param name="filePath">The file path to write the object instance to.</param>
	/// <param name="objectToWrite">The object instance to write to the file.</param>
	/// <param name="append">If false the file will be overwritten if it already exists. If true the contents will be appended to the file.</param>
	public static void WriteToXmlFile<T>(string filePath, T objectToWrite, bool append = false) where T : new()
	{
		TextWriter writer = null;
		try
		{
			var serializer = new XmlSerializer(typeof(T));
			writer = new StreamWriter(filePath, append);
			serializer.Serialize(writer, objectToWrite);
		}
		finally
		{
			if (writer != null)
				writer.Close();
		}
	}

	/// <summary>
	/// Reads an object instance from an XML file.
	/// <para>Object type must have a parameterless constructor.</para>
	/// </summary>
	/// <typeparam name="T">The type of object to read from the file.</typeparam>
	/// <param name="filePath">The file path to read the object instance from.</param>
	/// <returns>Returns a new instance of the object read from the XML file.</returns>
	public static T ReadFromXmlFile<T>(string filePath) where T : new()
	{
		TextReader reader = null;
		try
		{
			var serializer = new XmlSerializer(typeof(T));
			reader = new StreamReader(filePath);
			return (T)serializer.Deserialize(reader);
		}
		finally
		{
			if (reader != null)
				reader.Close();
		}
	}
}

 

And here is an example of how to use it:

public class Person
{
	public string Name { get; set; }
	public int Age = 20;
	public Address HomeAddress { get; set;}
	private string _thisWillNotGetWrittenToTheFile = "because it is not public.";

	[XmlIgnore]
	public string ThisWillNotBeWrittenToTheFile = "because of the [XmlIgnore] attribute.";
}

public class Address
{
	public string StreetAddress { get; set; }
	public string City { get; set; }
}

// And then in some function.
Person person = new Person() { Name = "Dan", Age = 30; HomeAddress = new Address() { StreetAddress = "123 My St", City = "Regina" }};
List<Person> people = GetListOfPeople();
XmlSerialization.WriteToXmlFile<Person>("C:\person.txt", person);
XmlSerialization.WriteToXmlFile<List<People>>("C:\people.txt", people);

// Then in some other function.
Person person = XmlSerialization.ReadFromXmlFile<Person>("C:\person.txt");
List<Person> people = XmlSerialization.ReadFromXmlFile<List<Person>>("C:\people.txt");

 

Writing and Reading an object to / from a Json file (using the Newtonsoft.Json assembly in the Json.NET NuGet package)

  • Only writes and reads the Public properties and variables to / from the file.
  • Classes to be serialized must contain a public parameterless constructor.
  • The data saved to the file is human readable, so it can easily be edited outside of your application.
  • Use the [JsonIgnore] attribute to exclude a public property or variable from being written to the file.
/// <summary>
/// Functions for performing common Json Serialization operations.
/// <para>Requires the Newtonsoft.Json assembly (Json.Net package in NuGet Gallery) to be referenced in your project.</para>
/// <para>Only public properties and variables will be serialized.</para>
/// <para>Use the [JsonIgnore] attribute to ignore specific public properties or variables.</para>
/// <para>Object to be serialized must have a parameterless constructor.</para>
/// </summary>
public static class JsonSerialization
{
	/// <summary>
	/// Writes the given object instance to a Json file.
	/// <para>Object type must have a parameterless constructor.</para>
	/// <para>Only Public properties and variables will be written to the file. These can be any type though, even other classes.</para>
	/// <para>If there are public properties/variables that you do not want written to the file, decorate them with the [JsonIgnore] attribute.</para>
	/// </summary>
	/// <typeparam name="T">The type of object being written to the file.</typeparam>
	/// <param name="filePath">The file path to write the object instance to.</param>
	/// <param name="objectToWrite">The object instance to write to the file.</param>
	/// <param name="append">If false the file will be overwritten if it already exists. If true the contents will be appended to the file.</param>
	public static void WriteToJsonFile<T>(string filePath, T objectToWrite, bool append = false) where T : new()
	{
		TextWriter writer = null;
		try
		{
			var contentsToWriteToFile = Newtonsoft.Json.JsonConvert.SerializeObject(objectToWrite);
			writer = new StreamWriter(filePath, append);
			writer.Write(contentsToWriteToFile);
		}
		finally
		{
			if (writer != null)
				writer.Close();
		}
	}

	/// <summary>
	/// Reads an object instance from an Json file.
	/// <para>Object type must have a parameterless constructor.</para>
	/// </summary>
	/// <typeparam name="T">The type of object to read from the file.</typeparam>
	/// <param name="filePath">The file path to read the object instance from.</param>
	/// <returns>Returns a new instance of the object read from the Json file.</returns>
	public static T ReadFromJsonFile<T>(string filePath) where T : new()
	{
		TextReader reader = null;
		try
		{
			reader = new StreamReader(filePath);
			var fileContents = reader.ReadToEnd();
			return Newtonsoft.Json.JsonConvert.DeserializeObject<T>(fileContents);
		}
		finally
		{
			if (reader != null)
				reader.Close();
		}
	}
}

And here is an example of how to use it:

public class Person
{
	public string Name { get; set; }
	public int Age = 20;
	public Address HomeAddress { get; set;}
	private string _thisWillNotGetWrittenToTheFile = "because it is not public.";

	[JsonIgnore]
	public string ThisWillNotBeWrittenToTheFile = "because of the [JsonIgnore] attribute.";
}

public class Address
{
	public string StreetAddress { get; set; }
	public string City { get; set; }
}

// And then in some function.
Person person = new Person() { Name = "Dan", Age = 30; HomeAddress = new Address() { StreetAddress = "123 My St", City = "Regina" }};
List<Person> people = GetListOfPeople();
JsonSerialization.WriteToJsonFile<Person>("C:\person.txt", person);
JsonSerialization.WriteToJsonFile<List<People>>("C:\people.txt", people);

// Then in some other function.
Person person = JsonSerialization.ReadFromJsonFile<Person>("C:\person.txt");
List<Person> people = JsonSerialization.ReadFromJsonFile<List<Person>>("C:\people.txt");

 

As you can see, the Json example is almost identical to the Xml example, with the exception of using the [JsonIgnore] attribute instead of [XmlIgnore].

 

Writing and Reading an object to / from a Json file (using the JavaScriptSerializer in the System.Web.Extensions assembly)

There are many Json serialization libraries out there.  I mentioned the Newtonsoft.Json one because it is very popular, and I am also mentioning this JavaScriptSerializer one because it is built into the .Net framework.  The catch with this one though is that it requires the Full .Net 4.0 framework, not just the .Net Framework 4.0 Client Profile.

The caveats to be aware of are the same between the Newtonsoft.Json and JavaScriptSerializer libraries, except instead of using [JsonIgnore] you would use [ScriptIgnore].

Be aware that the JavaScriptSerializer is in the System.Web.Extensions assembly, but in the System.Web.Script.Serialization namespace.  Here is the code from the Newtonsoft.Json code snippet that needs to be replaced in order to use the JavaScriptSerializer:

// In WriteFromJsonFile<T>() function replace:
var contentsToWriteToFile = Newtonsoft.Json.JsonConvert.SerializeObject(objectToWrite);
// with:
var contentsToWriteToFile = new System.Web.Script.Serialization.JavaScriptSerializer().Serialize(objectToWrite);

// In ReadFromJsonFile<T>() function replace:
return Newtonsoft.Json.JsonConvert.DeserializeObject<T>(fileContents);
// with:
return new System.Web.Script.Serialization.JavaScriptSerializer().Deserialize<T>(fileContents);

 

Happy Coding!

Categories: C#, Json, XML Tags: , , , , , , , , , , ,

Don’t Write WPF Converters; Write C# Inline In Your XAML Instead Using QuickConverter

December 13th, 2013 7 comments

If you’ve used binding at all in WPF then you more then likely have also written a converter.  There are lots of tutorials on creating converters, so I’m not going to discuss that in length here.  Instead I want to spread the word about a little known gem called QuickConverter.  QuickConverter is awesome because it allows you to write C# code directly in your XAML; this means no need for creating an explicit converter class.  And it’s available on NuGet so it’s a snap to get it into your project.

 

A simple inverse boolean converter example

As a simple example, let’s do an inverse boolean converter; something that is so basic I’m surprised that it is still not included out of the box with Visual Studio (and why packages like WPF Converters exist).  So basically if the property we are binding to is true, we want it to return false, and if it’s false, we want it to return true.

The traditional approach

This post shows the code for how you would traditionally accomplish this.  Basically you:

1) add a new file to your project to hold your new converter class,

2) have the class implement IValueConverter,

3) add the class as a resource in your xaml file, and then finally

4) use it in the Converter property of the xaml control.  Man, that is a lot of work to flip a bit!

Just for reference, this is what step 4 might look like in the xaml:

<CheckBox IsEnabled="{Binding Path=ViewModel.SomeBooleanProperty, Converter={StaticResource InverseBooleanConverter}" />

 

Using QuickConverter

This is what you would do using QuickConverter:

<CheckBox IsEnabled="{qc:Binding '!$P', P={Binding Path=ViewModel.SomeBooleanProperty}}" />

That it! 1 step! How freaking cool is that!  Basically we bind our SomeBooleanProperty to the variable $P, and then write our C# expressions against $P, all in xaml! This also allows us to skip steps 1, 2, and 3 of the traditional approach, allowing you to get more done.

 

More examples using QuickConverter

The QuickConverter documentation page shows many more examples, such as a Visibility converter:

Visibility="{qc:Binding '$P ? Visibility.Visible : Visibility.Collapsed', P={Binding ShowElement}}"

 

Doing a null check:

IsEnabled="{qc:Binding '$P != null', P={Binding Path=SomeProperty}"

 

Checking a class instance’s property values:

IsEnabled="{qc:Binding '$P.IsValid || $P.ForceAlways', P={Binding Path=SomeClassInstance}"

 

Doing two-way binding:

Height="{qc:Binding '$P * 10', ConvertBack='$value * 0.1', P={Binding TestWidth, Mode=TwoWay}}"

 

Doing Multi-binding:

Angle="{qc:MultiBinding 'Math.Atan2($P0, $P1) * 180 / 3.14159', P0={Binding ActualHeight, ElementName=rootElement}, P1={Binding ActualWidth, ElementName=rootElement}}"

 

Declaring and using local variables in your converter expression:

IsEnabled="{qc:Binding '(Loc = $P.Value, A = $P.Show) => $Loc != null &amp;&amp; $A', P={Binding Obj}}"

* Note that the "&&" operator must be written as "&amp;&amp;" in XML.

 

And there is even limited support for using lambdas, which allows LINQ to be used:

ItemsSource="{qc:Binding '$P.Where(( (int)i ) => (bool)($i % 2 == 0))', P={Binding Source}}"

 

Quick Converter Setup

As mentioned above, Quick Converter is available via NuGet.  Once you have it installed in your project, there are 2 things you need to do:

1. Register assemblies for the types that you plan to use in your quick converters

For example, if you want to use the Visibility converter shown above, you need to register the System.Windows assembly, since that is where the System.Windows.Visibility enum being referenced lives.  You can register the System.Windows assembly with QuickConverter using this line:

QuickConverter.EquationTokenizer.AddNamespace(typeof(System.Windows.Visibility));

In order to avoid a XamlParseException at run-time, this line needs to be executed before the quick converter executes.  To make this easy, I just register all of the assemblies with QuickConverter in my application’s constructor.  That way I know they have been registered before any quick converter expressions are evaluated.

So my App.xaml.cs file contains this:

public partial class App : Application
{
	public App() : base()
	{
		// Setup Quick Converter.
		QuickConverter.EquationTokenizer.AddNamespace(typeof(object));
		QuickConverter.EquationTokenizer.AddNamespace(typeof(System.Windows.Visibility));
	}
}

Here I also registered the System assembly (using “typeof(object)”) in order to make the primitive types (like bool) available.

 

2. Add the QuickConverter namespace to your Xaml files

As with all controls in xaml, before you can use a you a control you must create a reference to the namespace that the control is in.  So to be able to access and use QuickConverter in your xaml file, you must include it’s namespace, which can be done using:

xmlns:qc="clr-namespace:QuickConverter;assembly=QuickConverter"

 

So should I go delete all my existing converters?

As crazy awesome as QuickConverter is, it’s not a complete replacement for converters.  Here are a few scenarios where you would likely want to stick with traditional converters:

1. You need some very complex logic that is simply easier to write using a traditional converter.  For example, we have some converters that access our application cache and lock resources and do a lot of other logic, where it would be tough (impossible?) to write all of that logic inline with QuickConverter.  Also, by writing it using the traditional approach you get things like VS intellisense and compile-time error checking.

2. If the converter logic that you are writing is very complex, you may want it enclosed in a converter class to make it more easily reusable; this allows for a single reusable object and avoids copy-pasting complex logic all over the place.  Perhaps the first time you write it you might do it as a QuickConverter, but if you find yourself copy-pasting that complex logic a lot, move it into a traditional converter.

3. If you need to debug your converter, that can’t be done with QuickConverter (yet?).

 

Summary

So QuickConverter is super useful and can help speed up development time by allowing most, if not all, of your converters to be written inline.  In my experience 95% of converters are doing very simple things (null checks, to strings, adapting one value type to another, etc.), which are easy to implement inline.  This means fewer files and classes cluttering up your projects.  If you need to do complex logic or debug your converters though, then you may want to use traditional converters for those few cases.

So, writing C# inline in your xaml; how cool is that!  I can’t believe Microsoft didn’t think of and implement this.  One of the hardest things to believe is that Johannes Moersch came up with this idea and implemented it while on a co-op work term in my office!  A CO-OP STUDENT WROTE QUICKCONVERTER!  Obviously Johannes is a very smart guy, and he’s no longer a co-op student; he’ll be finishing up his bachelor’s degree in the coming months.

I hope you find QuickConverter as helpful as I have, and if you have any suggestions for improvements, be sure to leave Johannes a comment on the CodePlex page.

Happy coding!

Categories: C#, WPF, XAML Tags: , , , , , , ,

Adding and accessing custom sections in your C# App.config

September 25th, 2012 35 comments

Update (Feb 10, 2016): I found a NuGet package called simple-config that allows you to dynamically bind a section in your web/app.config file to a strongly typed class without having to write all of the boiler-plate code that I show here. This may be an easier solution for you than going through the code I show below in this post.

So I recently thought I’d try using the app.config file to specify some data for my application (such as URLs) rather than hard-coding it into my app, which would require a recompile and redeploy of my app if one of our URLs changed.  By using the app.config it allows a user to just open up the .config file that sits beside their .exe file and edit the URLs right there and then re-run the app; no recompiling, no redeployment necessary.

I spent a good few hours fighting with the app.config and looking at examples on Google before I was able to get things to work properly.  Most of the examples I found showed you how to pull a value from the app.config if you knew the specific key of the element you wanted to retrieve, but it took me a while to find a way to simply loop through all elements in a section, so I thought I would share my solutions here.

Due to the popularity of this post, I have created a sample solution that shows the full implementation of both of the methods mentioned below.

Simple and Easy

The easiest way to use the app.config is to use the built-in types, such as NameValueSectionHandler.  For example, if we just wanted to add a list of database server urls to use in my app, we could do this in the app.config file like so:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <configSections>
        <section name="ConnectionManagerDatabaseServers" type="System.Configuration.NameValueSectionHandler" />
    </configSections>
    <startup>
        <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
    </startup>
    <ConnectionManagerDatabaseServers>
        <add key="localhost" value="localhost" />
        <add key="Dev" value="Dev.MyDomain.local" />
        <add key="Test" value="Test.MyDomain.local" />
        <add key="Live" value="Prod.MyDomain.com" />
    </ConnectionManagerDatabaseServers>
</configuration>

And then you can access these values in code like so:

string devUrl = string.Empty;
var connectionManagerDatabaseServers = ConfigurationManager.GetSection("ConnectionManagerDatabaseServers") as NameValueCollection;
if (connectionManagerDatabaseServers != null)
{
    devUrl = connectionManagerDatabaseServers["Dev"].ToString();
}

Sometimes though you don’t know what the keys are going to be and you just want to grab all of the values in that ConnectionManagerDatabaseServers section.  In that case you can get them all like this:

// Grab the Environments listed in the App.config and add them to our list.
var connectionManagerDatabaseServers = ConfigurationManager.GetSection("ConnectionManagerDatabaseServers") as NameValueCollection;
if (connectionManagerDatabaseServers != null)
{
    foreach (var serverKey in connectionManagerDatabaseServers.AllKeys)
    {
        string serverValue = connectionManagerDatabaseServers.GetValues(serverKey).FirstOrDefault();
        AddDatabaseServer(serverValue);
    }
}

And here we just assume that the AddDatabaseServer() function adds the given string to some list of strings.

One thing to note is that in the app.config file, <configSections> must be the first thing to appear in the <configuration> section, otherwise an error will be thrown at runtime. Also, the ConfigurationManager class is in the System.Configuration namespace, so be sure you have

using System.Configuration

at the top of your C# files, as well as the “System.Configuration” assembly included in your project’s references.

So this works great, but what about when we want to bring in more values than just a single string (or technically you could use this to bring in 2 strings, where the “key” could be the other string you want to store; for example, we could have stored the value of the Key as the user-friendly name of the url).

More Advanced (and more complicated)

So if you want to bring in more information than a string or two per object in the section, then you can no longer simply use the built-in System.Configuration.NameValueSectionHandler type provided for us.  Instead you have to build your own types.  Here let’s assume that we again want to configure a set of addresses (i.e. urls), but we want to specify some extra info with them, such as the user-friendly name, if they require SSL or not, and a list of security groups that are allowed to save changes made to these endpoints.

So let’s start by looking at the app.config:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <configSections>
        <section name="ConnectionManagerDataSection" type="ConnectionManagerUpdater.Data.Configuration.ConnectionManagerDataSection, ConnectionManagerUpdater" />
    </configSections>
    <startup>
        <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
    </startup>
    <ConnectionManagerDataSection>
        <ConnectionManagerEndpoints>
            <add name="Development" address="Dev.MyDomain.local" useSSL="false" />
            <add name="Test" address="Test.MyDomain.local" useSSL="true" />
            <add name="Live" address="Prod.MyDomain.com" useSSL="true" securityGroupsAllowedToSaveChanges="ConnectionManagerUsers" />
        </ConnectionManagerEndpoints>
    </ConnectionManagerDataSection>
</configuration>

The first thing to notice here is that my section is now using the type “ConnectionManagerUpdater.Data.Configuration.ConnectionManagerDataSection” (the fully qualified path to my new class I created) “, ConnectionManagerUpdater” (the name of the assembly my new class is in).  Next, you will also notice an extra layer down in the <ConnectionManagerDataSection> which is the <ConnectionManagerEndpoints> element.  This is a new collection class that I created to hold each of the Endpoint entries that are defined.  Let’s look at that code now:

using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ConnectionManagerUpdater.Data.Configuration
{
    public class ConnectionManagerDataSection : ConfigurationSection
    {
        /// <summary>
        /// The name of this section in the app.config.
        /// </summary>
        public const string SectionName = "ConnectionManagerDataSection";

        private const string EndpointCollectionName = "ConnectionManagerEndpoints";

        [ConfigurationProperty(EndpointCollectionName)]
        [ConfigurationCollection(typeof(ConnectionManagerEndpointsCollection), AddItemName = "add")]
        public ConnectionManagerEndpointsCollection ConnectionManagerEndpoints { get { return (ConnectionManagerEndpointsCollection)base[EndpointCollectionName]; } }
    }

    public class ConnectionManagerEndpointsCollection : ConfigurationElementCollection
    {
        protected override ConfigurationElement CreateNewElement()
        {
            return new ConnectionManagerEndpointElement();
        }

        protected override object GetElementKey(ConfigurationElement element)
        {
            return ((ConnectionManagerEndpointElement)element).Name;
        }
    }

    public class ConnectionManagerEndpointElement : ConfigurationElement
    {
        [ConfigurationProperty("name", IsRequired = true)]
        public string Name
        {
            get { return (string)this["name"]; }
            set { this["name"] = value; }
        }

        [ConfigurationProperty("address", IsRequired = true)]
        public string Address
        {
            get { return (string)this["address"]; }
            set { this["address"] = value; }
        }

        [ConfigurationProperty("useSSL", IsRequired = false, DefaultValue = false)]
        public bool UseSSL
        {
            get { return (bool)this["useSSL"]; }
            set { this["useSSL"] = value; }
        }

        [ConfigurationProperty("securityGroupsAllowedToSaveChanges", IsRequired = false)]
        public string SecurityGroupsAllowedToSaveChanges
        {
            get { return (string)this["securityGroupsAllowedToSaveChanges"]; }
            set { this["securityGroupsAllowedToSaveChanges"] = value; }
        }
    }
}

So here the first class we declare is the one that appears in the <configSections> element of the app.config.  It is ConnectionManagerDataSection and it inherits from the necessary System.Configuration.ConfigurationSection class.  This class just has one property (other than the expected section name), that basically just says I have a Collection property, which is actually a ConnectionManagerEndpointsCollection, which is the next class defined.

The ConnectionManagerEndpointsCollection class inherits from ConfigurationElementCollection and overrides the required fields.  The first tells it what type of Element to create when adding a new one (in our case a ConnectionManagerEndpointElement), and a function specifying what property on our ConnectionManagerEndpointElement class is the unique key, which I’ve specified to be the Name field.

The last class defined is the actual meat of our elements.  It inherits from ConfigurationElement and specifies the properties of the element (which can then be set in the xml of the App.config).  The “ConfigurationProperty” attribute on each of the properties tells what we expect the name of the property to correspond to in each element in the app.config, as well as some additional information such as if that property is required and what it’s default value should be.

Finally, the code to actually access these values would look like this:

// Grab the Environments listed in the App.config and add them to our list.
var connectionManagerDataSection = ConfigurationManager.GetSection(ConnectionManagerDataSection.SectionName) as ConnectionManagerDataSection;
if (connectionManagerDataSection != null)
{
    foreach (ConnectionManagerEndpointElement endpointElement in connectionManagerDataSection.ConnectionManagerEndpoints)
    {
        var endpoint = new ConnectionManagerEndpoint() { Name = endpointElement.Name, ServerInfo = new ConnectionManagerServerInfo() { Address = endpointElement.Address, UseSSL = endpointElement.UseSSL, SecurityGroupsAllowedToSaveChanges = endpointElement.SecurityGroupsAllowedToSaveChanges.Split(',').Where(e => !string.IsNullOrWhiteSpace(e)).ToList() } };
        AddEndpoint(endpoint);
    }
}

This looks very similar to what we had before in the “simple” example.  The main points of interest are that we cast the section as ConnectionManagerDataSection (which is the class we defined for our section) and then iterate over the endpoints collection using the ConnectionManagerEndpoints property we created in the ConnectionManagerDataSection class.

Also, some other helpful resources around using app.config that I found (and for parts that I didn’t really explain in this article) are:

How do you use sections in C# 4.0 app.config? (Stack Overflow) <== Shows how to use Section Groups as well, which is something that I did not cover here, but might be of interest to you.

How to: Create Custom Configuration Sections Using Configuration Section (MSDN)

ConfigurationSection Class (MSDN)

ConfigurationCollectionAttribute Class (MSDN)

ConfigurationElementCollection Class (MSDN)

I hope you find this helpful.  Feel free to leave a comment.  Happy Coding!

Categories: .NET, C# Tags: , , , ,

Sweet C# Gems

September 2nd, 2011 No comments

James Michael Hare has a lot of awesome C# and .Net related posts, so this is just a little shout out to him (and my own little way of bookmarking his blogs since GWB doesn’t provide a way to "favourite" or "follow" him).  Of particular awesomeness is his C#/.NET Little Wonders and Pitfalls series, and the C#/.NET Fundamentals: Choosing the Right Collection Class.  Keep the great posts coming James!

Categories: .NET, C# Tags: ,

Some Visual Studio 2010 Shortcuts and C# 4.0 Cool Stuff

April 17th, 2011 1 comment

A list of some shortcus and new features to VS 2010 and C# 4.0:

  • Default values for parameters
  • Can access parameters by name (i.e. SomeFunction(name: "Dan", age: 26);
  • Can now put Labels on breakpoints and filter the breakpoints, as well as import and export breakpoints.
  • Window => New Window to open up same file in two separate tabs, or can drag the splitter at the top-right corner of the edit window.
  • Edit => Outlining => Hide Selection to collapse any region of code
  • Alt + Mouse Left Drag for box selection instead of line selection, then just start typing; you can also use Alt+Shift+Arrow Keys to do box selection with the keyboard.
  • Alt+Arrow Keys to move current line up/down.  Can also select multiple lines and use Alt+Up/Down to move the whole selection up/down.
  • In NavigateTo search window (Ctrl + Comma) use capitals to search for camel casing (i.e. CE to find displayCustomerEmails) and a space to do an "and" search (i.e. "email customer" would find displayCustomerEmails).
  • Ctrl + I to do an incremental search of a document, then F3 and Shift + F3 to move to next/previous matches.
  • Use snippets to automatically create code and save time.
  • Ctrl + Period to access VS tickler window instead of having to hover over the variable with the mouse.
  • Ctrl + Alt + Spacebar to change VS to suggest variable names instead of auto completing them.
  • Can right click in document to remove and sort using statements.
  • Enum.TryParse() has been added to match a string or number to an enumerated type.
  • Contract.Requires() and .Ensures() to ensure that function conditions are met (at compile time).
  • String.IsNullOrWhitespace(string);
  • Lazy<T> for thread-safe lazy loading of variables.
  • VS => Options => Debugging => Output Window => Data Binding to give more info about errors.
  • Using System.Threading.Tasks for parallel processing.  Parallel.For() and .ForEach
  • PLINQ => myCollection.InParallel().Where(x => …..);
  • New Dynamic keyword type => just like Object except not checked at compile time.
  • Ctrl+Shift+V to cycle through clipboard ring
  • Alt+Ctrl+Down to access tab menu
  • Ctrl+Shift+Up/Down to move between instances of the highlighted variable
  • Ctrl+] to move back and forth between a functions opening and closing braces (i.e. "{" and "}"). This appears to also work in XAML!
  • Alt+Arrow Keys to move current line up/down.  Can also select multiple lines and use Alt+Up/Down to move the whole selection up/down.
  • Rather than selecting a whole line first, just use Ctrl+C or Ctrl+X to Copy/Cut the entire line. You can also use Shift+Delete to delete an entire line without selecting it.