Immediate Window. Generating and executing lambdas across application domains.


First I’d like to say thank you words to Igor Moochnick. His article CodeDom extensions and dynamic LINQ (string/script to LINQ emitting) gave me a lot of pleasure extending it a bit and creating shorter code in a Linq manner flow. Refer to his article for more details on CodeDom and extension methods he introduced.

Introduction

Due to some purposes I needed creating a quick implementation of some kind of "Immediate Window" that could allow me executing methods and setting properties for object instances at live running application. I tried several approaches. Among them were "Dynamic Methods", extending "Linq Dynamic API" and parsing commands and property paths to be able using them against reflection. But at last moved to code generation as the most easiest and quickest way of accomplishing the task.

Imagine you have a small TextBox based pad in the running WPF application similar to "Immediate Window" pad in Visual Studio and you are willing to execute the following snippet against the main application window:

this.Title = "NewTitle"

(this.FindName("btnExecute") as Button).SetValue(Button.ContentProperty, "NewContent")

(this.FindName("stackPanel") as StackPanel).Children.Add(new Button() { Content="xxx" })

So these lines should be transformed into the code from their string representation and executed in runtime against the running Window as the code is supposed to perform some actions against the Window instance.

What I’ve decided to do was similar to the following ideas:

1. We should have the dynamically generated method that will have our text line as it’s body (though with some possible transformations)

2. Method should accept our Window instance as parameter and perform defined text line against parameter.

3. It should return something if we are requesting the property value.

So we need here something similar to the code we could write down manually in the application wrapped into a method, for example

this.Title = "NewTitle" can be imagined as following:

public static void SetTitle(Window obj, string value)
{
  obj.Title = value;
}

So upon processing the command our environment has to generate some method called for example "SetTitle", provide the execution context (in this case a Window) and pass the command typed by the user. During that it should redirect all "this" aliases to the execution context detected (in this case all "this" should be translated into "obj"). Regard this as you are typing the body of some method without body declaration and are sure that all the missing stuff will be automatically generated.

Implementation

Code generation for this case will require dealing with separate application domains due to assembly management issues and possible memory leaks. The steps will be as following:

1. Transform and wrap user defined method/function body with appropriate method, class, namespace, etc. declarations using the CodeDom (so to get the ready to compile sources either into memory or physical file)

2. Compile the resulting Dom into the assembly (I’ll be using physical files)

3. Create a separate application domain and load compiled assembly into it.

4. Extract the generated method from the loaded assembly and invoke it against the execution context (in this case it will be a Window)

5. Free resources, unload second application domain and perform a temporary files cleanup.

This is similar to implementing an Add-In or Plug-In support for your application where your external algorithms may be added to main application, executed against some provided execution context and finally destroyed without any impact on main application.

It is obvious that you might don’t want passing whole your window across application domain boundaries (i.e. .net Remoting scenario) and you don’t want marking anything as Serializable to pass into another domain. So all we need here is getting some delegate or lambda somewhere outside for applying it against our Window locally.

Void execution

Under Void execution I mean some operation that is invoked against your execution context and doesn’t return any results. For example setting the property value.

So what happens when user types this.Title = "New Title" and presses Enter or some "Execute" button

1. "this" alias is converted into "context"

2. Lambda action is generated that performs your logic against some "context" parameter:

Action<T> action = context => { context.Title = "New Title"; };

3. Wrapper method and class container is generated that will help you getting lambda from another domain:

namespace GraphSquare.AutoScript
{
  using System;
  using System.Windows;

  public class Script
  {
    public static Action<T> CreateLambda<T>() where T : Window
    {
      Action<T> action = context => { context.Title = "New Title"; }; 
      return action;
    }
  }
}

As you can see this method will be valid for all the types based on Window, so you’ll have possibilities running the resulting lambda against your different custom windows and dialogs that inherit Window type. Note that this rules are introduced for clarification purposes and <T> constraint may differ. According to this constraint we ensure that the method will be compiled successfully as each Window object has a Title property.

CodeDom for this method is generated using the Igor’s CodeDom extensions I mentioned at the beginning of the article:

public static CodeDom GenerateActionDom<T>(string actionBody)
{
  string body = string.Format(
    "Action<T> action = context => {{ {0}; }}; return action;",
    actionBody.Replace("this", "context"));

  CodeDom c = new CodeDom();
  c.AddReference(DefaultReferences)
      .AddNamespace(DefaultNamespace)
        .Imports(DefaultImports)
          .AddClass(
            c.Class(DefaultClassName)
              .AddMethod(c.LambdaAction("CreateLambda", typeof(T).Name, null, body))
           );

  return c;
}

I won’t dwell on extension methods implementation and my contribution to it as it is more understandable when looking through the sources. Please refer to the source code link at the end of this article. In two words you are creating the source for the class mentioned earlier and specifying the <T> constraint passing the generic type provided for the method. Also "this" alias is converted into "context" and passed to CodeDom as a body of newly generated method.

Function execution

If you want invoking the command that user had typed and expect some results to be returned and displayed you might want in this case getting Func<T,K> lambda, running it against some T parameter and present the K result back to user. For simplicity purposes I’ve decided to reuse native .net "return" keyword and so being close to method body declaration in a common way it is used.

So what happens when user types return this.Title and presses Enter or some "Execute" button:

1. "this" is converted into "context"

2. Lambda function is generated that performs some logic against your "context" and returns results

Func<T, object> func = context => { return context.Title; };

3. Wrapper function is generated for getting lambda from another domain, constraints and types are defined according to the calling application

namespace GraphSquare.AutoScript
{
  using System;
  using System.Windows;

  public class Script
  {
    public static Func<T, object> CreateLambda<T>() where T : Window
    {
      Func<T, object> func = context => { return context.Title; };
      return func;      
    }
  }
}

Here’s how CodeDom is generated to get such a class:

public static CodeDom GenerateFunctionDom<T>(string fucntionBody)
{
  string body = string.Format(
    "Func<T,object> func = context => {{ {0}; }}; return func;",
    fucntionBody.Replace("this", "context"));

  CodeDom c = new CodeDom();
  c.AddReference(DefaultReferences)
      .AddNamespace(DefaultNamespace)
        .Imports(DefaultImports)
          .AddClass(
            c.Class(DefaultClassName)
              .AddMethod(c.LambdaFunction("CreateLambda", typeof(T).Name, null, body))
           );

  return c;
}

Compilation and assembly loading

I’ve provided additional method for CodeDom class providing capabilities compiling sources to file without keeping the strong reference to Assembly file at the end so providing possibilities of removing the assembly later on when it is no more in use. You’ll be calling CodeDom.CompileAssembly method that gets string parameter for full final assembly path and returns CompilerResults for results processing in order compilation exceptions.

According to common approach patterns for loading assemblies inside separate application domains you need implementing a proxy Loader class to serve also as a contract and bridge between your two domains. So exactly the loader being instantiated in the second application domain will load compiled script assembly, extract the desired lambda and execute it against your context or simply return you the lambda so you can execute it inside the main application domain whenever required.

Assembly Loader

using System;
using System.IO;
using System.Reflection;

namespace GraphSquare.Scripting.CodeDom
{
  [Serializable]
  public class AssemblyLoader
  {
    Assembly assembly;

    public AssemblyLoader()
    {
      assembly = null;
    }

    // Loads the content of a file to a byte array to
    // prevent file locking, so user can remove or modify assembly 
    // while using it loaded into memory
    static byte[] LoadFile(string filename)
    {      
      FileStream fs = new FileStream(filename, FileMode.Open);
      byte[] buffer = new byte[(int)fs.Length];
      fs.Read(buffer, 0, buffer.Length);
      fs.Close();
      return buffer;
    }
    
    public void Load(string assemblyPath)
    {
      byte[] rawAssembly = LoadFile(assemblyPath);
      this.assembly = Assembly.Load(rawAssembly);
    }
  }
}

This is a basic implementation providing only assembly loading facilities. It will be extended later on. Note that it is situated in the separate assembly in order to serve a contract between different domains.

To create additional application domain our main application will have the following method:

private static AppDomain CreateNewDomain()
{
  // Create a simple application domain
  return AppDomain.CreateDomain(
    typeof(AssemblyLoader).Name, 
    AppDomain.CurrentDomain.Evidence, 
    AppDomain.CurrentDomain.SetupInformation);
}

This is the most basic implementation of second domain that takes Evidence and Setup Information from the main one and so loads all the references that the main domain has. In our case it will also load the contract library with the AssemblyLoader so we could establish communication between domains easily.

To create a valid loader in the second domain and loading external assembly file into it we’ll be using the following method:

private static AssemblyLoader CreateLoader(AppDomain domain, string assemblyPath)
{
  // Create a new instance of AssemblyLoader in the separate domain
  AssemblyLoader loader = domain.CreateInstanceAndUnwrap(
    "GraphSquare.Scripting", 
    typeof(AssemblyLoader).FullName) as AssemblyLoader;

  // Load compiled assembly into the loader
  loader.Load(assemblyPath);      
  return loader;
}

Extracting compiled lambdas

Fine now we have two possible members of the generated wrapper class needed to be discovered and loaded (action and function) to be used in lambda generation. As we have a separate domain with compiled assembly loaded into it and know exactly the namespace, type and name of the wrapper class and even the name of the method to generate lambda – "CreateLambda" (as we did it’s generation actually) the process of it’s loading and invokation becomes quite trivial.

Using Assembly.GetType(string…) method it becomes easy loading types and activating objects. For each type you can call GetMethod(…) to get the necessary method info to be used in invokaction. Thus discovering and invoking generic methods are a bit different. Here’s how can extract our generated "CreateLambda" method from AssemblyLoader:

public Action<T> GetLambdaAction<T>(string type, string action)
{
  // Extract type method info from assembly
  MethodInfo methodInfo = assembly.GetType(type).GetMethod(
    action, 
    BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static);

  // Create generic arguments for generic method
  Type[] genericArguments = new Type[] { typeof(T) };

  // Create generic function info for invokaction
  MethodInfo genericMethodInfo = methodInfo.MakeGenericMethod(genericArguments);

  // Invoke generic function and get return value as Action<T>
  Action<T> returnValue = (Action<T>)genericMethodInfo.Invoke(null, null);

  // return results
  return returnValue;
}

As compiled assembly is loaded into the second application domain where the AssemblyLoader is already present so loader is capable of discovering our generated type to work with further.

When executed this method returns us ready to use lambda with the body we defined earlier. In most of the cases guess you’ll have to get compiled lambda, execute it against some context and dispose it. So we can introduce two more members for the AssemblyLoader for invoking actions and functions directly from AssemblyLoader.

public bool InvokeLambdaAction<T>(string type, string action, T argument)
{      
  // Extract type method info from assembly
  MethodInfo methodInfo = assembly.GetType(type).GetMethod(
    action, 
    BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static);

  // Create generic arguments for generic method
  Type[] genericArguments = new Type[] { typeof(T) };

  // Create generic function info for invokaction
  MethodInfo genericMethodInfo = methodInfo.MakeGenericMethod(genericArguments);

  // Invoke generic function and get return value as Action<T>
  Action<T> returnValue = (Action<T>)genericMethodInfo.Invoke(null, null);
  if (returnValue != null)
  {
    // Execute received action against argument provided
    returnValue(argument);
    return true;
  }
  return false;
}

public object InvokeLambdaFunc<T>(string type, string function, T argument)
{
  // Extract type method info from assembly
  MethodInfo methodInfo = assembly.GetType(type).GetMethod(
    function, 
    BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static);

  // Create generic arguments for generic method
  Type[] genericArguments = new Type[] { typeof(T) };
  // Create generic function info for invokaction
  MethodInfo genericMethodInfo = methodInfo.MakeGenericMethod(genericArguments);
  // Invoke generic function and get return value as Func<T,K>
  Func<T, object> func = (Func<T, object>)genericMethodInfo.Invoke(null, null);
  //return execution result of func against the argument provided
  return func(argument);
}

As you can see both methods are not so different. Both of them require full type name of the class holding the method, method or function name to be searched and argument of your needed type to be processed as an execution context.

So the process of executing user typed command that doesn’t require results can be as following (at main application side):

// Generate CodeDom
CodeDom c = CodeDomSmith.GenerateActionDom<T>(methodBody);
string assemblyPath = GenerateAssemblyPath();
// Compile sources into assembly
CompilerResults results = c.CompileAssembly(assemblyPath);

// Process compilation errors
if (results.Errors.Count > 0)
  return false;

// Create separate application domain
AppDomain domain = CreateNewDomain();
// Create loader proxy based on application domain created 
// and load compiled assembly to it
AssemblyLoader proxy = CreateLoader(domain, assemblyPath);

try
{
  // Extract and execute lambda against the context object
  proxy.InvokeLambdaAction<T>(
    CodeDomSmith.DefaultClassFullname, "CreateLambda", context);
}
catch (Exception ex)
{
  return false;
}

if (domain != null)
{
  // Unload and dispose second application domain
  AppDomain.Unload(domain);
  domain = null;
}
if (File.Exists(assemblyPath))
  // Remove used assembly
  File.Delete(assemblyPath);

The only difficulty that arise is determining what type of lambda to generate according to the user input. I mean how to decide whether he wants executing a Void or getting some results. I’ve accomplished that again as I’ve mentioned earlier by reusing the "return" keyword. So due to this sample when the user starts the command from "return" keyword we are generating the Func<T,K> otherwise Action<T>

Samples:

Here’s the sample environment I’ve prepared for the article:

image

You’ll have the Window that will be assigned as an execution context for all upcoming commands typed in the bottom TextBox control.

"Execute" button compiles and executes the command putting all the output to the "Debug window" TextBox control. You will also be able to see the content of the class generated and executed for development purposes.

"Help" button shows a list of dummy samples that can be copy-pasted and tested against the window.

"Execution Result" TextBox shows the results of the command execution. This can be either "void()" if method was compiled and executed or some value.

Here’s the possible result of execution of the command:

this.Title = "GraphSquare Scripting"

image

Note that execution result is "void()" as we didn’t try to return anything and the Title of the window has changed from "Window1" to "GraphSquare Scripting"

Let’s try running the application once again and executing the following command:

return this.Title == "Window1"

image

As you can see command was successfully evaluated and returned "True" value that is a valid result as the Window’s Title property value is "Window1"

Now let’s try typing a command that cannot be valid and compiled by default, something like

this.ExecuteMissingCommand()

If you remember the execution context for our commands is being set to Window. This means that as a common Window class does not contain the method typed the resulting code won’t be compiled and cannot be executed against a window. This brings to a compilation exception:

image

The exception message will be the following:

error CS1061: ‘T’ does not contain a definition for ‘ExecuteMissingCommand’ and no extension method ‘ExecuteMissingCommand’ accepting a first argument of type ‘T’ could be found (are you missing a using directive or an assembly reference?)

This is mainly for your debugging purposes. The real life implementation can hide the developer oriented details and present more user-friendly message.

Also as you might have noticed all lambda generation methods are generic ones, for example

public static bool InvokeContextMethod<T>(T context, string methodBody, ...)

this means that you can specify different execution contexts or even change them on the fly.

As for the suggestions I think there could be some contracts to serve as execution context instead of applications or windows. Remember not providing the end-user more power that he is expected to have. As you will see from the samples provided within the "Help" section of this tool you can simply add or remove new elements to the window, rename buttons, etc.

Hope this helps someone enriching his tools with runtime command support or Debug features.

The source code for the article can be found here

Providing simple collaboration support for your diagramming tools with WCF services.


Notes: This article assumes you are already familiar with WCF services or studying them.

Several months ago I’ve posted simple draft project for a small diagramming tool. Though I didn’t intend it to be a tool or starter kit it is still the most visited post among all other more interesting things 😉 As I’ve been playing with WCF and wanted some simple environment for testing some ideas I remembered about old CTP project and found it was quite a good playground for my experiments. So this article will be using the reviewed and edited version of the project mentioned in the old article.

I’d also recommend you visiting the Code Project to see the wonderful samples by Marcus. I’ve dared to take his toolbox and tool item implementation for my article samples 🙂

What is the key changes made since the previous sample:

1. Simple MVC pattern implementation sample

The classes introducing the pattern are:

DiagramView: WPF canvas hosting the shapes and connection lines

DiagramController: Simply the controller

DiagramModel: Data model hosting the business objects (entities) that are not related to presentation layer.

As my intention was processing business objects rather that shapes and controls I’ve decided to perform a dummy bridging between raw "DiagramEntity" classes and their UI representation.

I’ve also simplified event system between Model, Controller and View based on Action<DiagramEntity> delegates for clarity purposes. Model is capable only of storing the entities, adding them and removing. In this implementation the View is also responsible for instantiating the Collaboration Client that will be described later on.

2. Unity Application Block

I’ve reduced the influence of the service bus for many parts of the application in favor to Unity Application Block. That made my life much easier.

3. Toolbox

As I moved on for using a simple toolbox I’ve eliminated the shape tools and shape creators that were rudimentary parts of Factory design pattern. But left the connection creator tools with a simple Strategy pattern implementation just for educational purposes.

4. Extensions and IExtensibleObject<T> interface

In this article I’ve described some ideas for extending Canvas panels by means of IExtensibleObject<T> interface taken from WCF. I’ve decided it would be fair enough reusing this stuff to show that it’s working fine. The Canvas (View) is extended with Selection and Drag functionality that can be simple switched off if required.

5. Aero theme by default and many minor improvements…

Here’s how it looks like

image

 

Basic collaboration support using WCF service

My intention was giving some sketches for how it could be implemented and some raw material for starting to play with. So I’ll be concentrating on it omitting thread safeties, error checking and the stuff like that for clarity purposes. Guess it would be much easier extending the sources based raw skeleton implementation.

Business objects

Entities

As I’ve mentioned the entities my service will be operating on are not related to presentation layer so it won’t be aware of WPF and the stuff like that. It will be the View responsibility turning them into the visuals and applying different styles and templates. Meanwhile we need at least some basic UI related information be passed like positioning coordinates so this is what UIEntity class serves for. I’ll be playing with three entities named "DataEntity", "SystemEntity" and "UserEntity" that will be turned later on to the appropriate shapes at client side. This provides nice presentation flexibility allowing different clients using specific visuals and styles though following one remote model.

Remote Model and Remote Callbacks

I’ve chosen the Duplex WCF service for the sample that requires implementing a callback contract also. For more details on duplex services better refer to MSDN library as it might take long time for me describing theory that is already perfectly presented 😉

This is how the remote model might look like:

using System.ServiceModel;

namespace Collaboration.Contracts
{
  [ServiceContract(
    Name = "RemoteModel",
    Namespace = "http://dvuyka.spaces.live.com/diagramming/types",
    CallbackContract = typeof(IRemoteModelCallback),
    SessionMode = SessionMode.Required)]
  [ServiceKnownType(typeof(UserEntity))]
  [ServiceKnownType(typeof(DataEntity))]
  [ServiceKnownType(typeof(SystemEntity))]
  public interface IRemoteModel
  {
    [OperationContract(IsOneWay = true)]
    void AddEntity(DiagramEntity entity);

    [OperationContract(IsOneWay = true)]
    void RemoveEntity(DiagramEntity entity);

    [OperationContract(IsOneWay = true)]
    void Connect();
  }
}

Due to serialization purposes our model should be aware of all the inheritances that might take part in the collaboration process. I’ve declared them as "known" to the service being described by this interface. Our remote model will also provide Adding and Removing capabilities like the "local" tool’s model and subscription to service via the Connect method.

The callback contract might look like the following:

using System.ServiceModel;

namespace Collaboration.Contracts
{
  public interface IRemoteModelCallback
  {
    [OperationContract(IsOneWay = true)]
    void OnEntityAdded(DiagramEntity entity);

    [OperationContract(IsOneWay = true)]
    void OnEntityRemoved(DiagramEntity entity);
  }
}

It means that remote model (or simply service) will be raising "OnEntityAdded" and "OnEntityRemoved" events for all the subscribers providing them with the entities to be immediately added to the local model and so presented with the View.

Wiring up the "local" model

At the client side we are creating a simple wrapper delegating remote model events to the local model like the following

using Collaboration.Contracts;

namespace HomeDiagramming.Collaboration
{  
  public sealed class RemoteModelCallback : IRemoteModelCallback
  {
    public DiagramModel LocalModel { get; private set; }

    public RemoteModelCallback(DiagramModel localModel)
    {
      this.LocalModel = localModel;
    }

    #region IRemoteModelCallback Members

    public void OnEntityAdded(DiagramEntity entity)
    {
      this.LocalModel.AddEntity(entity);
    }

    public void OnEntityRemoved(DiagramEntity entity)
    {
      this.LocalModel.RemoveEntity(entity);
    }

    #endregion
  }
}

So each time the service will be publishing "OnEntityAdded" or "OnEntityRemoved" events to it’s subscribers the event execution will be delegated to the underlying local model by calling it’s appropriate members.

The client connecting our remote model will be as simple as possible:

using System.Diagnostics;
using System.ServiceModel;
using System.ServiceModel.Channels;
using Collaboration.Contracts;

namespace HomeDiagramming.Collaboration
{
  [DebuggerStepThrough]
  public class RemoteModelClient : DuplexClientBase<IRemoteModel>, IRemoteModel
  {
    public RemoteModelClient(InstanceContext callbackInstance) :
      base(callbackInstance)
    {
    }

    public RemoteModelClient(InstanceContext callbackInstance, Binding binding, 
EndpointAddress address)
      : base(callbackInstance, binding, address)
    {      
    }

    #region IRemoteModel Members

    public void AddEntity(DiagramEntity entity)
    {
      base.Channel.AddEntity(entity);
    }

    public void RemoveEntity(DiagramEntity entity)
    {
      base.Channel.RemoveEntity(entity);
    }

    public void Connect()
    {
      base.Channel.Connect();
    }

    #endregion
  }
}

During creation of the View that instantiates the Controller we can initialize our remote controller in the following way

InstanceContext context = new InstanceContext(new RemoteModelCallback(this.Controller.Model));
NetTcpBinding binding = new NetTcpBinding();
EndpointAddress address = new EndpointAddress("net.tcp://localhost:8080/RemoteModel");    
remoteModel = new RemoteModelClient(context, binding, address);
remoteModel.Connect();

Remote model skeleton

And finally here comes the raw skeleton for the remote model

using System;
using System.Collections.Generic;
using System.ServiceModel;
using Collaboration.Contracts;

namespace Collaboration.Service
{
  [ServiceBehavior(
    InstanceContextMode = InstanceContextMode.Single, 
    ConcurrencyMode=ConcurrencyMode.Multiple)]
  public class RemoteModel : IRemoteModel
  {
    // TODO: should be the thread-safe collections
    private List<DiagramEntity> entities = new List<DiagramEntity>();
    private List<IRemoteModelCallback> callbacks = new List<IRemoteModelCallback>();

    #region IRemoteModel Members

    public void AddEntity(DiagramEntity entity)
    {
      // TODO: should be performed in a thread-safe manner and fully async
      Console.WriteLine("Adding entity :" + entity.Name);
      lock (entities)
      {
        this.entities.Add(entity);        
      }

      Console.WriteLine("Entity added. Total count: " + entities.Count);
      IRemoteModelCallback callback = GetCallback();      
      foreach (IRemoteModelCallback c in callbacks)
        if (c != callback)
          c.OnEntityAdded(entity);
    }

    public void RemoveEntity(DiagramEntity entity)
    {
      // TODO: should be performed in a thread-safe manner      
    }

    public void Connect()
    {
      IRemoteModelCallback callback = GetCallback();
      if (!callbacks.Contains(callback))
      {        
        callbacks.Add(callback);
        Console.WriteLine("User connected. Total count: " + callbacks.Count);
      }
    }

    private IRemoteModelCallback GetCallback()
    {
      return OperationContext.Current.GetCallbackChannel<IRemoteModelCallback>();
    }

    #endregion
  }
}

As you can see it is a Singleton service with Multiple ConcurrencyMode. Each connected client will be registered within the subscribers collection (callbacks). Each model change causes all the subscribers to be notified.

In my implementation each client immediately applies changes to the Model and View. Guess the rest of functionality might depend on your ideas.

The source code for the article can be  found here:

Possible issues:

If you encounter exceptions related to connection try changing the ports for your endpoints. On some machines localhost:8080 may be not allowed. Change it to localhost:8000 ("App.config" for server and "DiagramView.cs" for client) or whatever port is available free and doesn’t violate your firewall policy.

Notes: In order to build solution you’ll need the release version of Unity Application Block. Solution is configured to run both service and demo application at a time. Open the binaries folder for demo application and run several instances of application in order to ensure all clients receive notifications and create shapes at a time.

Injecting Xaml with Unity Application Block using Markup Extensions. Part 4.


Delegating Routed Events (Event Handlers).

This is a continued research dedicated to Unity Application Block.

For more details please refer to the following posts

Part 1. Basic injection of custom user controls.

Part 2. Injection of standard WPF controls. Setting properties for injected controls.

Part 3. Attached dependency properties. Binding delegation. Code behind support.

To be honest I didn’t expect myself splitting the topic across 4 posts. And I didn’t plan writing the 4rth one until I collect a batch of features to be presented. But after yesterdays playing with injections I decided that I have to implement and share with one more helpful feature as event delegation. This will be a good ending for the series until I collect feedbacks and ideas to be able to continue it.

What’s the purpose injecting WPF (or 3rd party) controls without specifying event handlers from my current page like for the common controls? This was the question I wanted to answer myself yesterday. As I’ve started the way injection extension behaved itself in a maximum intuitive manner I definitely wanted to set event handlers in the common manner too (meaning intellisense, generation of new handler within the current page, etc).

I tried to follow the "Setters" approach for properties and make the standard "EventSetter" class suite my needs but encountered some difficulties with it’s implementation. So the easiest and quickest solution was following the "PropertySetter" approach and introduce another placeholder for the event.

Again I’ve decided to change the naming 🙂 Everything being wrapped by the custom classes were suffixed with the "Injector". PropertySetter became PropertyInjector, BindingSetter became BindingInjector and so new event setter became EventInjector accordingly. This was mainly done to follow one scheme and not to affect existing extensions’ names.

So here’s what I wanted to have as a result

image

Unity Control extension provides additional collection for storing ready to delegation event handlers. You have the possibility of specifying appropriate routed event and assign or generate event handler for it like you would do for the common Button control.

EventInjector itself is represented by the following holder:

public class EventInjector
{
  public RoutedEvent Event { get; set; }
  public event RoutedEventHandler Handler;

  public bool IsValid
  {
    get { return Event != null && Handler != null; }
  }

  public void AssignTo(FrameworkElement element)
  {
    if (IsValid)
      element.AddHandler(Event, Handler);
  }
}

Unity Control extension keeps the list of assigned EventInjector objects until the underlying UI control is resolved within the Unity Container. After that all event handlers are assigned for the control. Rather simple approach that might require enhancements in your implementations. Anyway does it’s job 🙂

You can specify a chain of "Button.Click" events or specify a set of different routed events, everything will be delegated to the underlying control until control has the routed event being assigned.

Guess this single and small extension finishes the basic feature set that is required to move your controls to another abstraction level and provide possibilities for hot changing/patching of your UI elements via the application configuration file.

Source code for the article

Injecting Xaml with Unity Application Block using Markup Extensions. Part 3.


Attached dependency properties. Bindings. Code behind support.

This is a continued research dedicated to Unity Application Block.

For more details please refer to the following posts

Part 1. Basic injection of custom user controls.

Part 2. Injection of standard WPF controls. Setting properties for injected controls.

Introduction

After having played by myself with injector markup extension implementation described in the previous article I found out a lot of limitations that could be easily introduced.

I used "PropertySetter" wrapper for delegating properties to the injected elements based on dependency property descriptors taken from string representation of property names. This restricted me either from setting common non-dependency properties or supporting Attached Properties. Though good for panel layouts injected controls for example couldn’t be properly positioned for the Canvas.

Another thing I wanted to have is ability for delegating dependency property bindings to injected control. This could be also a very interesting task as I found no ways of declaring Binding markup extension within the Xaml that are having deferred processing/execution.

Third feature I was looking for is correct referencing injected controls from the code behind. I wanted to be fully transparent delegating the names of UnityControl extensions to the injected controls so having possibilities of addressing them via .FindName(…) method

As the mission was successfully accomplished I’m putting the most interesting details here…

Prerequisites

As we are going to deal with Bindings we need getting one level upper in the type mapping as UIElement doesn’t support bindings. We will be using FrameworkElement for binding purposes. This requirement slightly impacts the Application Configuration File we are using for Container initialization. Instead of UIElement contract we have to declare FrameworkElement alias and map all the controls to it.

Here’s the sample:

<typeAlias alias="FrameworkElement" type="System.Windows.FrameworkElement, PresentationFramework, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>

The rest of the control aliases remain the same.

The container types are mapped to this alias accordingly like the following:

<types>
  <type type="FrameworkElement" mapTo="Button" name="UnityButton"/>
  <type type="FrameworkElement" mapTo="TabControl" name="UnityTabControl"/>
  <type type="FrameworkElement" mapTo="TextBox" name="UnityTextBox"/>
  <type type="FrameworkElement" mapTo="ListBox" name="UnityListBox"/>
</types>

(Attached) Dependency Properties Support

While it is more convenient maintaining dependency properties using DependencyPropertyDescriptor, common "plain" properties are maintained using Reflection – PropertyInfo. I’ve decided to decouple these two worlds to have capability of deciding which approach is more appropriate in this or that situation.

I’m using the standard Setter class for targeting (attached)dependency properties as this class may seem more intuitive than custom control implementation. Setter class also deals with DependencyProperty object and so provides native way of controlling the values defined. This is how our injection declaration looks like:

<this:UnityControl Name="btn1" Container="defaultProvider" Dependency="UnityButton">
    <this:UnityControl.Setters>
        <Setter Property="FrameworkElement.Height" Value="50"/>
        <Setter Property="Canvas.Left" Value="100"/>
        <Setter Property="Canvas.Top" Value="100"/>
    </this:UnityControl.Setters>
    
    <this:UnityControl.Properties>
        <this:PropertySetter Property="Content" 
                             Value="{StaticResource resourceString}"/>                    
    </this:UnityControl.Properties>
</this:UnityControl>

As you can see UnityControl extension now contains a collection property "Setters" accepting objects of "Setter" type. "Setters" collection is processed using dependency property descriptors only.

"Properties" collection property accepts objects of "PropertySetter" type and is processed using PropertyInfo. This means that PropertySetter can be also defined for a common dependency property, but it doesn’t support attached dependency properties. So as you can see this modification provides backwards compatibility for the samples from the previous article.

Main purpose of using standard Setter class as I’ve said earlier is restricting users from defining plain strings for property names. For the markup be valid each setter must have any valid dependency property defined. Thus PropertySetter accepts string based values and is more error prone. Each approach has it’s advantages and disadvantages so it’s up to you deciding which and at what time to use.

Dependency Property Binding Delegation

As you can understand the markup extensions’ inner world from the previous articles it’s quite difficult to control standard Binding markup extension. And guess it’s nearly impossible (at least for current version of WPF) subclassing it or providing deferred initialization/execution mechanisms. This means we cannot use default Binding extension for delegation purposes as we cannot control it’s life cycle.

The most easiest way was to follow the "PropertySetter" approach and introducing "BindingSetter" class for wrapping most basic functionality for establishing a binding.

Here’s the source code for such a wrapper:

public sealed class BindingSetter
{
  public DependencyProperty Property { get; set; }
  public string ElementName { get; set; }
  public DependencyProperty Path { get; set; }
  public BindingMode Mode { get; set; }
  public IValueConverter Converter { get; set; }
  public object ConverterParameter { get; set; }
  public object FallbackValue { get; set; }
}

So the main task for UnityControl extension will be enumerating the setters defined and constructing appropriate Bindings for the resolved FrameworkElement.

Let’s take a Canvas panel and inject the TextBox based control by "UnityTextBox" name like the following:

<this:UnityControl Name="txtBox" 
                   Container="defaultProvider" 
                   Dependency="UnityTextBox" 
                   Content="Default">
    <this:UnityControl.Setters>
        <Setter Property="FrameworkElement.Width" Value="100"/>
    </this:UnityControl.Setters>
</this:UnityControl>

Next let’s inject a Button based control named "UnityButton":

<this:UnityControl Name="btn1" Container="defaultProvider" Dependency="UnityButton">
    <this:UnityControl.Setters>
        <Setter Property="FrameworkElement.Height" Value="50"/>
        <Setter Property="Canvas.Left" Value="100"/>
        <Setter Property="Canvas.Top" Value="100"/>
    </this:UnityControl.Setters>
    
    <this:UnityControl.Bindings>
        <this:BindingSetter 
            Property="ContentControl.Content" 
            ElementName="txtBox" 
            Path="TextBox.Text" 
            Mode="OneWay"
            Converter="{StaticResource testConverter}"
            ConverterParameter="[{0}]"/>
    </this:UnityControl.Bindings>
</this:UnityControl>

Button will be have a Height value of 100 and will be positioned at (100,100) point at the Canvas. Also we define a one way binding between Button.Content and TextBox.Text. Also for demonstration purposes I’ve configured simple value converter and converter parameter. Converter is formatting the input string according to parameter template.

image

UnityControl markup extension takes the element resolved via Unity Container and configures the Binding manually. Of course it is not fully functional and there’s no MultiBinding support (guess this will require another enhancement for future articles) but demonstrates that it is possible to do.

 

Code Behind Support

It is obvious that you won’t get all the required functionality by declaring xaml only. It logically comes out that next thing you might require is accessing the injected elements from code behind. This is also required for Binding establishment. You might have already noticed the "Name" attribute definition in the samples above.

<this:UnityControl Name="txtBox" 
                   Container="defaultProvider" 
                   Dependency="UnityTextBox" 
                   Content="Default">
    <this:UnityControl.Setters>
        <Setter Property="FrameworkElement.Width" Value="100"/>
    </this:UnityControl.Setters>
</this:UnityControl>

Note that my implementation of Name property is not the same as x:Name markup extension. Name property is used in this case for delegating x:Name for the control being injected using the Unity Container. It is not mandatory so you can omit it if not required.

Upon injection UnityControl extension takes the Namescope of the parent container and registers the newly resolved element within it’s scope using the Name property if it was defined.

This brings out that the following Window.Loaded event handler be fully functional:

void Window1_Loaded(object sender, RoutedEventArgs e)
{      
  // Get the control injected with the UnityControl extension
  TextBox txtBox = canvas.FindName("txtBox") as TextBox;
}  

So this means that declaring injection in the Xaml you still have access to the element being injected and not taking care about the injector markup itself.

The source code for the article can be found here.

Injecting Xaml with Unity Application Block using Markup Extensions. Part 2.


Notes: This article assumes that you are familiar or started playing with a Unity Application Block. I won’t dwell on describing it’s architecture or manuals so please refer to the link mentioned for more details.

Introduction

In the previous article I’ve described how user custom controls can be injected into Xaml markup without code behind operations using custom Markup Extensions. I’ve mentioned that there might be more easy way of introducing common WPF controls without any need for subclassing. So my second article will cover this very situation.

Aliases and Type Mapping

Similar to declaring contract interfaces and mapping all the required types to single content you can have no predefined contract. Dealing with UI controls common UIElement class may serve perfectly well as a contract. Especially if you noticed that my UnityReference markup extension was dealing with UIElement objects mainly.

So UIElement alias declaration within our "App.config" file can be the following

<typeAlias alias="UIElement" type="System.Windows.UIElement, PresentationCore, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>

Similar to the line above you are able to declare aliases for any set of controls required for your use in the Unity Container. Here’s what I’ll be playing with later on:

<typeAlias alias="Button" type="System.Windows.Controls.Button, PresentationFramework, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
<typeAlias alias="TabControl" type="System.Windows.Controls.TabControl, PresentationFramework, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
<typeAlias alias="TextBox" type="System.Windows.Controls.TextBox, PresentationFramework, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
<typeAlias alias="ListBox" type="System.Windows.Controls.ListBox, PresentationFramework, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>

As you can see I’ve just declared four standard controls.

Container definition is extremely simple

<container name="containerOne">
        <types>
          <type type="UIElement" mapTo="Button" name="UnityButton"/>
          <type type="UIElement" mapTo="TabControl" name="UnityTabControl"/>
          <type type="UIElement" mapTo="TextBox" name="UnityTextBox"/>
          <type type="UIElement" mapTo="ListBox" name="UnityListBox"/>
        </types>
      </container>

All the controls are mapped under base UIElement type. Each control name is prefixed with a "Unity*" to bring more clearance in the markup (this is just for testing purposes and you can provide any name you want).

Container Provider and Configuration  Markup Extension

Both Container Provider and Configuration extension remains unchanged so you can refer to the previous post or source code for more detailed information.

UnityControl Markup Extension

Here comes the most important part. UnityControl markup extension is based on the previous "UnityReference" one though extended with a set of more efficient facilities.

Support for property setters

As this extension is being transformed into UIElement it is obvious that we might want defining some properties not covered with initialization phase or whatever. For this very purpose I’ve introduced dedicated collection of my custom "PropertySetter" classes. PropertySetter contains only two properties: "Property(string)" and "Value(object)"

Here’s the basic example what I’m talking about

<this:UnityControl Container="defaultProvider" Dependency="UnityListBox">                
    <this:UnityControl.Properties>
        <this:PropertySetter Property="Background" Value="Wheat"/>
        <this:PropertySetter Property="Height" Value="100"/>
        <this:PropertySetter Property="ItemsSource">
            <this:PropertySetter.Value>
                <x:Array Type="sys:String">
                    <sys:String>Hello</sys:String>
                    <sys:String>World</sys:String>
                </x:Array>
            </this:PropertySetter.Value>
        </this:PropertySetter>
    </this:UnityControl.Properties>
</this:UnityControl>

Here I’ve injected some UI control named "UnityListBox", specified Background and Height. Also I’ve provided a list of strings to be applied as an ItemsSource.

<this:UnityControl Container="defaultProvider" Dependency="UnityTabControl">
    <this:UnityControl.Properties>
        <this:PropertySetter Property="Height" Value="100"/>
        <this:PropertySetter Property="ItemsSource">
            <this:PropertySetter.Value>
                <x:Array Type="TabItem">
                    <TabItem Header="Page1"/>
                    <TabItem Header="Page2"/>
                </x:Array>
            </this:PropertySetter.Value>
        </this:PropertySetter>
    </this:UnityControl.Properties>
</this:UnityControl>

Here I’ve injected a "UnityTabControl" element and predefined two pages of TabItem type.

The property/value conversion procedure is rather dummy and the subject to change but you are able configuring some properties and getting the basic idea. Note that I’ve supported only Dependency Properties.

Default Content Property Support

Next thing I wanted a lot is specifying the Content of UIElement in the common WPF manner without declaring any additional tags. Most of the standard controls have some properties marked with the ContentPropertyAttribute pointing to the property that will be defined when specific declaration is omitted.

For this case I’ve also implemented additional property "Content" for my markup extension and delegated it’s value to the control being injected with the container.

Here’s the sample:

<this:UnityControl Container="defaultProvider" Dependency="UnityButton">
    <this:UnityControl.Properties>                    
        <this:PropertySetter Property="Height" Value="50"/>
    </this:UnityControl.Properties>                
    <Image Source="Images/data.png" Width="32" Height="32" Stretch="Uniform"/>                
</this:UnityControl>

In this sample I’m injecting "UnityButton" element defining it’s Height property value. Also pay attention to the Image control declaration as a default content. This will be delegated to the button’s content after injection. Omitting the properties you can use the following declaration either:

<this:UnityControl Container="defaultProvider" Dependency="UnityButton">
    <Image Source="Images/data.png" Width="32" Height="32" Stretch="Uniform"/>                
</this:UnityControl>

The content can be also defined using the following markup

<this:UnityControl Container="defaultProvider" Dependency="UnityTextBox" Content="Default text"/>

In this sample I’m injecting the "UnityTextBox" control providing the Content as "Default text" string. As TextBox defines "TextProperty" dependency property as a default content I’ve defined the TextBox text here.

image

Conclusion

This approach may help you dynamically configuring your UI without rebuilding main application. Changing the type mapping or introducing new aliases you bring more power and extensibility. Any time any control can be patched or changed to completely new implementation.

Note: I’ve rebuild Unity targeting .net 3.5 framework. Binaries can be found in the "binaries" folder of the project.

Source code for the article