Lambda Dependencies Update
I just uploaded an update of my Lambda Dependencies library which fixes a bug with the weak event proxy. The update contains the fix and some minor optimizations.
Lambda Dependencies 1.0.1: dependencies.zip
I just uploaded an update of my Lambda Dependencies library which fixes a bug with the weak event proxy. The update contains the fix and some minor optimizations.
Lambda Dependencies 1.0.1: dependencies.zip
I’ve never been really happy with the commercial data grid I’ve been using so far – the whole API felt somewhat “winformish”, and required my to write a lot of XAML or even code for even the most basic tasks.
Today, I needed a simple grid on one of my current projects, and immediately got annoyed by the same issues that bug me every time. With the difference that this time, I had a new alternative to look at – Microsoft’s Data Grid that went V1 this October.
Well: This is an amazing control. It’s not amazingly powerful, it doesn’t have amazing animations, amazing views or anything like that. There is just one thing: It gets the job done.
Here’s my top 3 in comparison to my commercial product:
Finally I have data binding the way I always thought it should be. No more dealing with the internal data representation of the grid, and 2-way-data binding to selected items (not records or rows) out of the box. I didn’t even have to look up the API – it’s just as I expected it to be. Loving it:
<dg:DataGrid x:Name="platforms" ItemsSource="{Binding Path=Track.Platforms, ElementName=me}" SelectedItem="{Binding Path=ActivePlatform, ElementName=me}"> <!-- column definitions --> </dg:DataGrid>
To my great surprise, I can easily star-size columns to take the full available horizontal space of the grid. This is a feature I need as good as every time I use a grid. With my commercial product, I was forced to write a whole layout template in order to get there. Not anymore:
<dg:DataGrid.Columns> <!-- fixed size column --> <dg:DataGridTextColumn Header="Name" Width="60" Binding="{Binding Path=ItemName}" /> <!-- takes 2/3 of the remaining space --> <dg:DataGridTextColumn Header="Description" Width="2*" Binding="{Binding Path=Description}" /> <!-- takes 1/3 of the remaining space --> <dg:DataGridTextColumn Header="Position" Width="*" Binding="{Binding Path=StartPosition}" /> </dg:DataGrid.Columns>
I really do like some of the carefully crafted themes of my commercial grid. But on the other hand, customizing it was a major pain, so styling was one of my main concerns. However, the MS grid is amazingly flexible and easy to use for a v1.0 solution.
In the end, I’m happier with my custom-styled result than the predefined theme of my commercial grid – simply because the custom style blends in perfectly with the rest of the UI:
I’m pretty sure that the commercial – and definitely more powerful – solutions have their rightful place on the market, but Microsoft’s grid really fills a gap for me here – especially because of the API that just keeps things simple.
I can’t help but think that the vendors that were the first ones on the market may be last in the long run. At least the API of the grid I used so far just doesn’t cut it for me. We all had to get (are still getting) acquainted to “thinking in WPF” and some of the “mature” solutions just give me the impression that their basic concepts have “Windows Forms” written all over them. And with regards to compatibility, it might get pretty hard to get rid of that. That is, however, just my 0.02$.
Go get it @ CodePlex: http://www.codeplex.com/wpf
This is the second part of an article that covers the usage of lambda expressions to monitor changes on complex object graphs. The first part can be found here and the third part (Lambda Binding) is here.
Latest Version: 1.0.3, 2009.04.03
Download Project: lambda-dependencies.zip
The first part covered the basics of the framework based on a sample application where I monitored any changes on the object graph MyStudent.School.Address.City with a simple lambda expression:
public MyApplication() { //create a dependency on the city of the student's school var dep = DependencyNode.Create(() => MyStudent.School.Address.City); }
The subsequent chapters discuss a few advanced topics that might be important when working with the API.
In order to pick up a changed values on the dependency chain, the observed classes (in the sample: School, Student, Address) must implement the INotifyPropertyChanged interface. Otherwise, changes remain undetected.
This might not be a problem in case of immutable properties or fields, and it is perfectly valid to include classes that do not implement the interface. However: In case you don’t have INotifyPropertyChanged available (e.g. because you rely on a class in an external library), and changes do occur, you can manually update these node values by invoking the SetNodeValue method of an arbitrary dependency node.
public void SetFieldDependency() { Student student = TestUtil.CreateTestStudent(); //create dependency on the address field rather than the Address property var dep = DependencyNode.Create(() => student.School.address.City); dep.DependencyChanged += (node, e) => Console.WriteLine("City: " + e.TryGetLeafValue()); //exchange address var newAddress = new Address {City = "Stockholm"}; student.School.address = newAddress; //get the node that represents the address var addressFieldNode = dep.FindNode(() => student.School.address); //set the node value manually and trigger change event addressFieldNode.SetNodeValue(newAddress, true); }
In the sample above, we declared a dependency on the City property of an Address object. City is just a string, but what if we wanted to track *any* change on the school’s address? One way would be to declare dependencies for every single property of the address:
var student = TestUtil.CreateTestStudent("Harvard"); //create dependency on City var dep1 = DependencyNode.Create(() => student.School.Address.City); //create dependency on Street var dep2 = DependencyNode.Create(() => student.School.Address.Street); //...
This, however, is pretty tedious and there is a simpler solution: As Address implements INotifyPropertyChanged, we can just declare a dependency on the Address property of School.
var student = TestUtil.CreateTestStudent("Harvard"); //create dependency on address object var dep1 = DependencyNode.Create(() => student.School.Address); //output the changed property name and the change reason dep1.DependencyChanged += (node, e) => { string msg = "Changed property: {0}, change reason: {1}"; Console.Out.WriteLine(msg, e.ChangedMemberName, e.Reason); }; //change the city student.School.Address.City = "Ethon";
The above snippet registers with the DependencyChanged event and writes two properties of the event’s DependencyChangeEventArgs to the console: ChangedMemberName and the Reason. This produces the following console output:
Changed property: City, change reason: SubPropertyChanged
Note that this is a special case: The declared dependency chain is Student:School:Address while we received a change event for the City property, which is not part of the dependency chain!
I think that usually, this is a desired behavior, so this is the default. However, you can control this behavior by using a DependencyNodeSettings class and explicitly setting the ObserveSubValueChanges property:
var student = TestUtil.CreateTestStudent("Harvard"); //create settings class var settings = new DependencyNodeSettings<Address>(() => student.School.Address); settings.ChangeHandler = OnDependencyChanged; //configure settings to ignore sub item changes settings.ObserveSubValueChanges = false; //does not cause a change event: Student.School.Address.City = "Ethon";
Note that the same behavior goes for target items that are collections. If the target collection implements the INotifiyCollectionChanged interface, the dependency node fires the DependencyChanged event with a reason of TargetCollectionChange as soon as the contents of the targeted collection changes.
A DependencyNode only maintains weak references. Even if it would not pick up an object that goes out of scope because no property change event was fired, this still wouldn’t stop the targeted object from being garbage collected. The same goes for node’s events and internal event listeners.
I’m using two very nice implementations for internal listeners and the exposed DependencyChanged event:
This library solves a specific problem and currently operates solely on members, variables, and constant expressions – more complex expressions (such as LINQ queries) are currently out of the picture, but I’m open to suggestions. You might also look out for related projects, such as Bindable LINQ.
This is the first part of an article that covers the usage of lambda expressions to monitor changes on complex object graphs.
The second part can be found here.
The third part (Lambda Bindings) can be found here.
Latest Version: 1.0.3, 2009.04.03
Download Project: lambda-dependencies.zip
In an ongoing project, I had to struggle with quite a few dependencies between objects, mainly with regards to validation. As a result, I came up with a generic solution based on lambda expressions.
But let’s start with an example. Imagine you have an application that references a Student that attends a a given School. And let’s assume, the school’s location (city) is of importance to you, so a changed city should trigger some action. My class model looks like this:
In order to keep track of the dependency on the school’s location, you have to observe quite a few things:
This is a lot of error-prone and tedious work: You need to register and de-register event listeners, handle null references (a new School instance might not provide an Address at first) etc. This is where expression trees come to the rescue. Basically, you can reduce the plumbing to a single line of code:
public MyApplication() { //create a dependency on the city of the student's school DependencyNode<string> dependency; dependency = DependencyNode.Create(() => MyStudent.School.Address.City); }
The snippet above analyzes the submitted expression and resolves the dependency graph, which basically looks the following:
Dependency.Create returns an object of type DependencyNode. This node refers to the root of the expression tree, which is the MyApplication class that provides the MyStudent property. You can traverse the dependency chain in both directions through the ChildNode and ParentNode properties should you ever want to. But usually (if at all!), you’ll need just two properties:
//get the city, if the dependency graph leads to a valid address string city = dependency.IsChainBroken ? "NONE" : dependency.LeafValue;
(Note that LeafValue is a generic property. In this case, it is of type string)
As soon as a dependency is declared, the DependencyNode tries to register event listeners on all objects of the dependency graph in order to track changes and keep itself up-to-date. Furthermore, you can register an event listener with the node’s DependencyChanged event, which fires whenever a change in the dependency chain occurs. Event listeners receive an instance of DependencyChangeEventArgs that provide the changed node, property or field names, and the change reason:
Here’s a sample – the snippet below registers an event listener which basically just outputs the name of the student, the school name, and the city to the console:
public MyApplication() { //create a dependency on the city of the student's school dependency = DependencyNode.Create(() => MyStudent.School.Address.City); dependency.DependencyChanged += OnStudentCityChanged; } /// <summary> /// Invoked whenever the dependency graph between <see cref="MyStudent"/> /// property and the <see cref="Address.City"/> of the student's /// school is being changed. /// </summary> private void OnStudentCityChanged(object sender, DependencyChangeEventArgs<string> e) { //get the changed node DependencyNode<string> changedNode = e.ChangedNode; //get student name, if we have one after all string studentName = myStudent == null ? "[none]" : myStudent.Name; //get the school name string school = "[none]"; if (myStudent != null && myStudent.School != null) { school = myStudent.School.SchoolName; } //get the city, if the dependency graph leads to a valid address string city = changedNode.IsChainBroken ? "[unavailable]" : changedNode.LeafValue; //NOTE: You can also get the leaf value through this convenience method: //string city = e.TryGetLeafValue("[unavailable]"); //write student/city to console string msg = "Student {0} goes now to school {1} in {2}"; Console.Out.WriteLine(msg, studentName, school, city); }
Once an event listener is registered, you can change properties on different levels of the dependency chain:
public void Test() { //assign a student MyStudent = new Student { Name = "Lucy" }; //set a school without an address MyStudent.School = new School {SchoolName = "University"}; //assign an address MyStudent.School.Address = new Address {City = "Redmond"}; //assign another address instance MyStudent.School.Address = new Address {City = "New York"}; //change the City property of the address MyStudent.School.Address.City = "Washington"; //cut the graph by removing the school reference MyStudent.School = null; //clear the MyStudent property completely MyStudent = null; }
Every line of the above test method triggers the change event. Accordingly, the console output is the following:
Student Lucy goes now to school [none] in [unavailable] Student Lucy goes now to school University in [unavailable] Student Lucy goes now to school University in Redmond Student Lucy goes now to school University in New York Student Lucy goes now to school University in Washington Student Lucy goes now to school [none] in [unavailable] Student [none] goes now to school [none] in [unavailable]
Enjoy 🙂
I was struggling with IronPython today as I stumbled over a pretty annoying setback when it came to dynamic compilation of scripts that involved namespace imports.
Lets do an artificial sample: The snippet below just increments a variable by one. As expected, it executes blazingly fast – after compilation, it executes a few thousand times without getting over a single millisecond:
value = value + 1
Now look at the following example:
import clr clr.AddReference('System.Xml') from System.Xml import * value = value + 1
Basically, this snippet performs the same logic (incrementing the ‘value’ variable), but it contains an import for the System.Xml namespace. It’s not necessary, but it still needs to be compiled. Executing this (compiled!) script 4000 times takes over 5 seconds!
However: If you are lucky (as me), you have the opportunity to separate namespace imports and business logic, so you basically end up with two scripts:
//script 1 import clr clr.AddReference('System.Xml') from System.Xml import * //script 2 value = value + 1
Of course, you still need the import from the first script to perform the second one – which is where symbol dictionaries come into play:
//a dictionary that receives the import simbols var importSymbols = new SymbolDictionary(); //execute imports on our engine ScriptSource importSource = engine.CreateScriptSourceFromString(imports, SourceCodeKind.Statements); CompiledCode importCompiled = importSource.Compile(); //create a scop to populate the symbols with the imported types ScriptScope importScope = engine.CreateScope(importSymbols); importCompiled.Execute(importScope);
The statement above executes the import script with an empty SymbolDictionary. If you check this dictionary after execution, you can see that it now contains symbols for all types of the imported namespace:
importSymbols.Key = __builtins__ value = IronPython.Runtime.PythonDictionary importSymbols.Key = clr value = Microsoft.Scripting.Runtime.Scope importSymbols.Key = IHasXmlNode value = IronPython.Runtime.Types.PythonType importSymbols.Key = IXmlLineInfo value = IronPython.Runtime.Types.PythonType importSymbols.Key = IXmlNamespaceResolver value = IronPython.Runtime.Types.PythonType ... much more
What we can do now is reuse this retrieved symbols for our actual worker snippet (but beware, there’s a catch):
//compile worker script ScriptSource scriptSource = engine.CreateScriptSourceFromString(source, SourceCodeKind.Statements); CompiledCode workerScript = scriptSource.Compile(); //creating our scope with the new symbols allows us to access //the XML namespace ScriptScope workerScope = engine.CreateScope(importSymbols); workerScope.SetVariable("value", 10); workerScript.Execute(workerScope);
However, this code is not thread-safe, because it causes different scopes to actually share not only the import symbols, but all variables through the symbol dictionary. Look at the code below, that creates to script scope instances which are initialized with individual values:
//create a new scope with the symbols of the import scope ScriptScope run1 = engine.CreateScope(importSymbols); //start with a value of 10 run1.SetVariable("value", 10); workerScript.Execute(run1); //create a second scope with the symbols of the import scope ScriptScope run2 = engine.CreateScope(importSymbols); //start with a value of 20 run2.SetVariable("value", 20); workerScript.Execute(run2); //both scopes actually share the same variable Console.Out.WriteLine(run1.GetVariable<int>("value")); Console.Out.WriteLine(run2.GetVariable<int>("value"));
The console outputs the same value both times – because both scopes operate on the same variable:
21 21
So basically, we have two requirements:
We can do this by subclassing the CustomSymbolDictionary class of the Microsoft.Scripting.Runtime.BaseSymbolDictionary namespace. Took me ages to find a solution, but implementation was a breeze:
/// <summary> /// A symbol dictionary that provides an fixed set of /// symbols through a <see cref="SharedScope"/>. As new variables /// are not added to the <see cref="SharedScope"/>, these cached /// symbols can be reused across different scopes. /// </summary> public class SharedSymbolDictionary : CustomSymbolDictionary { /// <summary> /// A script scope that provides a reusable set of symbols. /// Any variables that are being created by the <see cref="ScriptScope"/> /// that owns this cache are not stored within <see cref="SharedScope"/>, /// but the parent scope's own symbol dictionary. /// </summary> public ScriptScope SharedScope { get; private set; } /// <summary> /// Creates a new cache instance /// </summary> /// <param name="sharedScope">A reusable <see cref="ScriptScope"/> that provides /// a set of symbols that are supposed to be used across several scopes.</param> /// <exception cref="ArgumentNullException">If <paramref name="sharedScope"/> /// is a null reference.</exception> public SharedSymbolDictionary(ScriptScope sharedScope) { if (sharedScope == null) throw new ArgumentNullException("sharedScope"); SharedScope = sharedScope; } /// <summary> /// Invoked if a given variable or symbol is being requested. This method /// tries to find the requested item in the underlying <see cref="SharedScope"/>. /// </summary> /// <param name="key"></param> /// <param name="value"></param> /// <returns>True if the <see cref="SharedScope"/> provides the requested /// symbol.</returns> protected override bool TryGetExtraValue(SymbolId key, out object value) { //return the key from the base scope, if possible. lock (SharedScope) { return SharedScope.TryGetVariable(SymbolTable.IdToString(key), out value); } } /// <summary> /// Gets a list of the extra keys that are cached by the the optimized /// implementation of the module. /// </summary> public override SymbolId[] GetExtraKeys() { lock (SharedScope) { return SharedScope.GetItems().Select(pair => SymbolTable.StringToId(pair.Key)).ToArray(); } } /// <summary> /// Tries to set the extra value and return true if the specified key /// was found in the list of extra values.<br/> /// Any attempts to store extra values are being denied, which causes /// them to be stored in the scope itself rather than the local /// <see cref="SharedScope"/>. This ensures that runtime variables are /// not shared between different instances of the cache. /// </summary> /// <param name="key">The key that is used to store the submitted /// value.</param> /// <param name="value">Value to be cached.</param> /// <returns>Always false because runtime symbols are not supposed /// to be stored within the cache. This causes the value to be stored /// within the internal dictionary of the base class.</returns> protected override bool TrySetExtraValue(SymbolId key, object value) { return false; } }
With this implementation, we can change our snippet accordingly:
//create a new scope with the symbols of the import scope SharedSymbolDictionary cache = new SharedSymbolDictionary(importScope); ScriptScope run1 = engine.CreateScope(cache); //start with a value of 10 run1.SetVariable("value", 10); workerScript.Execute(run1); //create a second scope with the symbols of the import scope cache = new SharedSymbolDictionary(importScope); ScriptScope run2 = engine.CreateScope(cache); //start with a value of 20 run2.SetVariable("value", 20); workerScript.Execute(run2); //both scopes actually share the same variable Console.Out.WriteLine(run1.GetVariable<int>("value")); Console.Out.WriteLine(run2.GetVariable<int>("value"));
11 21
And the performance gain is remarkable: Execution time is once again down to 17 milliseconds for 10’000 iterations 🙂
Download cache implementation and test script: symbolcache.zip
If you check the registry for (un-)installation information about installed applications, you can notice that the InstallLocation registry key is mostly empty. This is because most installers do not set ARPINSTALLLOCATION property to the value of [TARGETDIR] during installation. Unfortunately, this also includes Visual Studio setup projects:
What we can do so solve this problem is inserting a simple Type 51 Custom Action into the installer. What I was looking for, was an easy solution to automate this tasks (rather than editing them with ORCA or any other tool), and I eventually came up with a post-build event that updates the MSI database directly. Fortunately, I had a similar script in place from an earlier setup, so adjusting it was quite easy 🙂
In the link below, you can find a VBS script (SetArpInstallLocation.vbs) that inserts the required custom action for you and makes sure the ARPINSTALLLOCATION property is set during installation. All you have to do is calling the script during the post-build event of your setup project.
In the sample below, the script file has been placed in the same folder as the installation project. Accordingly, the build action looks like this:
"$(ProjectDir)SetArpInstallLocation.vbs" "$(BuiltOuputPath)"
If the installer file is re-built with this script in place, the installer writes the InstallLocation properly to the registry during installation 😀
Download VBS script file: SetArpInstallLocation.vbs