How to access private class members using Linq Expressions

This article is intended for cases where you are willing/forced to access a private member of a class.

That means you are not willing/able to change the code that defines the member.

If you need to access the member for many many instances of the class, “GetFieldAccessor” will save your cpu some time.

Properties and methods are accessible by creating “open instance delegates” via Delegate.CreateDelegate.

As discussed here: Use delegate to get values for FieldInfo, “Field access isn’t performed via a method (like getters and setters)–it’s performed with an IL instruction–so there’s nothing you can assign to a delegate. you’ll have to use the expression route to create a “block” of code (effectively IL) that can be assigned to a delegate.”

Previous to the introduction of Linq Expressions, Reflection would have been your only option.

Usage:

public class TestClass
{
    public TestClass(int i) { privateField = i; }
    private int privateField;
}
 
private void Test()
{
    var list = Enumerable.Range(0, 10000000).Select(i => new TestClass(i)).ToList();
    // old way: use FieldInfo
    var fieldInfo = typeof(TestClass).GetField("privateField"BindingFlags.GetField | BindingFlags.NonPublic | BindingFlags.Instance);
    var w = Stopwatch.StartNew();
    for (int i = 0; i < list.Count; i++)
    {
        var val = (int)fieldInfo.GetValue(list[i]);
        if (val != i)
            throw new InvalidOperationException();
    }
    w.Stop();
    // new way: use Expression.Field
    var accessor = GetFieldAccessor<TestClassint>("privateField");
    var w2 = Stopwatch.StartNew();
    for (int i = 0; i < list.Count; i++)
    {
        var val = accessor(list[i]);
        if (val != i)
            throw new InvalidOperationException();
    }
    w2.Stop();
    // ~ 7%
    Console.WriteLine(100.0 / (w.ElapsedTicks / w2.ElapsedTicks) + "%");
}

Both variants do the expensive Reflection part only once, outside of the for-loop.

The compiled delegate takes less than 10% cpu time. (compared to Reflection)

Here is the code for GetFieldAccessor:

public static Func<T, TResult> GetFieldAccessor<T, TResult>(string fieldName)
{
    var instExp = System.Linq.Expressions.Expression.Parameter(typeof(T));
    var fieldExp = System.Linq.Expressions.Expression.Field(instExp, fieldName);
    return System.Linq.Expressions.Expression.Lambda<Func<T, TResult>>(fieldExp, instExp).Compile();
} 

One last point: If you are forced to use .NET before 3.5 but still need additional performance:

  • Use Reflection.Emit to create a method that returns the private member
  • Then use an open instance delegate

Startnew Is Dangerous

Recently I was developing an ActionQueue. It supports serial asynchronous execution of Sytem.Action<ICancellationToken> delegates. I ran into a problem similar to this: Memory leak in recursive continuation Tasks I have a state object (e.g. of type Tuple<,,,>) and I pass this to Task.Factory.StartNew and if I run a memory profiler on my application I see that those state objects are not GC’ed. (Go is of type System.Action<object>).

// state is never released:
var task = Task.Factory.StartNew(Go, state);
 
// same problem:
var task = new Task(Go, state, TaskCreationOptions.DenyChildAttach | TaskCreationOptions.HideScheduler);
task.Start(TaskScheduler.Default);

My implementation had the assumption that “task” would represent the entire “Go” method but it represents only the first (synchronous) part if “Go” points to an asynchronous method (one that uses the async keyword). Some additional insight can be found here: http://blog.stephencleary.com/2013/08/startnew-is-dangerous.html The reason for the memory leak is that my implementation spawns continuations whose AsyncState recursively contains information about the previous Task. (In a memory profiler you will probably see its backing field “m_State”) Since you can’t reset the AsyncState property of Task (it is readonly and Dispose() does not clear it) all your Tasks and all their states will stay alive. This will not happen if you capture the state variable by passing a lambda expression to Task.Run:

// this works:
var task = Task.Run(() => Go(state));

So Task.Factory.StartNew is not only dangerous because of the reasons stated by Stephen Cleary, but also because it tempts you to use Task.AsyncState which also can be dangerous.

Multiple Inheritance

I you are developing a somewhat bigger project, sooner or later you will find yourself in a situation when you have already wasted your one and only allowed base class and say “It would be nice if this class could also derive from another one”. Well it wouldn’t. But that is a different story. Still, the problem can be solved in different ways:

Of course just the first one is meant seriously.

Let’s first take a look at why we want inheritance in the first place:

Two reasons: Polymorphism and Maintainability.

In my case the focus lies on maintainability. We do not want to have duplicate code. Or to be more specific, no duplicate code that is handwritten and therefore has an impact on maintainability. T4 templates to the rescue! http://msdn.microsoft.com/de-de/library/ee844259(v=vs.100).aspx 

I have some interfaces that many of my classes (ViewModels in my case) have to implement, and those ViewModels already have a base class. The interfaces are used by central behavior and manager classes that help organizing and unifying the user interface. The implementation of those interfaces is always the same, most of them just define some properties and the implementation takes care of the INotifyPropertyChanged.PropertyChanged event being raised properly.

Here is an example of such an interface:

IExecutableItem.cs

   public interface IExecutableItem
   {
        public ICommand Command { get; set; }
        public object CommandParameter { get; set; }
        public event CommandExecutedEventHandler Executed;
   }

Now with the help of T4 templates you can do this:

1.) Your create a partial class for your ViewModel that contains your handwritten code.

MyViewModel.cs

    public partial class MyViewModel : ViewModelBase
    {
        public MyViewModel(IServiceLocator serviceLocator)
            : base(serviceLocator)
        {  }
        // [ more code ... ]
    }

2.) You create a T4 Template File that generates the implementation of additional interfaces:

MyViewModel.ModelProperties.tt

<#@ template hostspecific="true" language="C#" #>
<#@ output extension=".cs" #>
<#@ include file="..\ModelProperties\ModelProperties.tt" #>
<#
	Implement(
		@"..\ModelProperties\",
		"ISelectableItem;IExecutableItem;IOrderedItem"
	);
#>

3.) You are done.

To make this work you need the included file ModelProperties.tt and one .tt file per interface you wish to be implementable in this way. I will give you the interface .tt for the IExecutableItem interface as an example:

IExecutableItem.tt

<#@ template debug="false" hostspecific="true" language="C#" #>
<#@ import namespace="System.Runtime.Remoting.Messaging" #>
<#@ import namespace="System.Collections.Generic" #>
<#@ parameter name="ClassName" type="System.String" #>
<#@ parameter name="Namespace" type="System.String" #>
<#
	var usings = (List<string>)CallContext.GetData("usings");
	usings.Add("using System.Windows.Input;");
	usings.Add("using MyCompany.MyProject.Tools;");
#>
namespace <#=Namespace#>
{

    public partial class <#=ClassName#> : IExecutableItem
    {

        private ICommand _Command;

        /// <summary>
        /// Command
        /// </summary>
        public ICommand Command
        {
            get { return _Command; }
            set
            {
                if (_Command != value)
                {
                    _Command = value;
                    base.RaisePropertyChanged(() => Command);
                }
            }
        }

        private object _CommandParameter;

        /// <summary>
        /// CommandParameter
        /// </summary>
        public object CommandParameter
        {
            get { return _CommandParameter; }
            set
            {
                if (_CommandParameter != value)
                {
                    _CommandParameter = value;
                    base.RaisePropertyChanged(() => CommandParameter);
                }
            }
        }

        private event CommandExecutedEventHandler _Executed;

        /// <summary>
        /// Executed
        /// </summary>
        public event CommandExecutedEventHandler Executed
        {
            add { _Executed += value; }
            remove { _Executed -= value; }
        }

    }

}

and here is the ModelProperties.tt:

<#@ template debug="false" hostspecific="true" language="C#" #>
<#@ output extension=".cs" #>
<#@ assembly name = "System.Core" #>
<#@ import namespace="System.IO" #>
<#@ import namespace="System.Collections.Generic" #>
<#@ import namespace="System.Linq" #>
<#@ import namespace="System.Runtime.Remoting.Messaging" #>
<#@ import namespace="Microsoft.VisualStudio.TextTemplating" #>
<#+

		public void Implement(string path, string interfaces)
		{
			TextTemplatingSession session = new TextTemplatingSession();
			session["Namespace"] = "MyCompany.MyProject.Demo";
			session["ClassName"] = "MyViewModel";
			var usings = new List<string>();
			CallContext.SetData("usings", usings);
			var sessionHost = (ITextTemplatingSessionHost) this.Host;
			sessionHost.Session = session;
			foreach (var item in interfaces.Split(';'))
			{
				GenerationEnvironment.Append(ProcessTemplate(Path.Combine(path, item.Trim() + ".tt")));
			}
			this.GenerationEnvironment.Insert(0, Environment.NewLine);
			foreach (var item in usings.Distinct().OrderByDescending(x => x))
			{
				this.GenerationEnvironment.Insert(0, item + Environment.NewLine);
			}
		}

		public string ProcessTemplate(string templateFileName)
		{
			string templateDirectory = Path.GetDirectoryName(Host.TemplateFile);
			string template = File.ReadAllText(Host.ResolvePath(templateFileName));
			Engine engine = new Engine();
			string output = engine.ProcessTemplate(template, Host);
			return output + Environment.NewLine;
		}

#>

The Implement method creates a session and stores the classname and the namespace in it. It also stores a stringlist in the CallContext to allow the interface .tt’s to add usings to the output. Then each interface .tt is executed and the output is added. Finally the content of the using stringlist is made distinct, sorted and inserted at the top of the generated file.

You end up with a ViewModel that has all the implementations from your interface .tt files. I know this is not “real” inheritance but it serves our main goal: Maintainability. Changes in the interface .tt files will be reflected in all “derived” classes once you hit “Transform all templates” again.

You could also combine this idea with the aforementioned “Simulated Multiple Inheritance Pattern” and make your templates generate all the redirecting methods. That way you would end up being able to also extend classes instead of just interfaces. I’ll leave this to you as a an exercise 😉

This is still not an out-of-the-box solution because you have to make all classes and interfaces “implementable” but usually you have only some base classes and interfaces and many many classes deriving from them.

First Dig

Welcome.

This is my first post. No source code, (nearly) no content, just the promise that you might find both of them on this page soon. My current project is a media player/library sort of thing. It will be based on WPF and WCF and is intended to be the new UI for my HTPC. I developed it’s predecessor in 2009 (TouchMenu) as a WinForms App.

I tried many of the available solutions but could not find one that matched my needs. The main reason was that most players were not operable without a mouse and/or keyboard attached to the HTPC. I want the final solution to have a high WAF (women acceptance factor) and I want it to be highly intuitive and responsive.

The hardware configuration is an Origen S21T case with built-in touchscreen and remote control. The case contains an Intel Atom mainboard.

The feature goals for the new version are:

– UI that can be used by touchscreen only. And by remote control only as well.

– Rating feature for currently playing title affecting its frequency of occurrence.

– Separate video playback window that can be placed/fullscreened on any of the detected monitors. (using either touchscreen or remote).

– Playlist management with import/export functionality from winamp and media player.

– USB Device Import feature

– CD playback with optional title and cover download

I hope to get the first evaluation version ready for download in the next six months. Please leave any suggestions or wishes as comments.