Показаны сообщения с ярлыком C#. Показать все сообщения
Показаны сообщения с ярлыком C#. Показать все сообщения

вторник, 5 октября 2010 г.

Introducing UStatic: check Unity injection statically

A few months ago I’ve made post about wrapper over Unity container that allows to verify object structure during compilation. At that time this wrapper supports only one type of injection – through properties (setter injection). Today it evolve into more evil and aggressive creature that besides property injection can initialize objects through calling specified constructors (constructor injection) and invoking methods.

Basically idea remains the same: we use lambdas for collecting user-defined configuration and describe dependencies as expression trees (amazing stuff, BTW! it can be applied to solve dozens of problems, from describing queries to being source for automatic generation of WPF ViewModels). With properties everything is pretty trivial:

using System;
using Microsoft.Practices.Unity;
using UStatic;

namespace UStaticTest
{
class Program
{
static void Main()
{
var container = new UnityContainer();

container.RegisterType<AnotherTestObject>(
c => c
.SetName("Test1")
.SetValueProperty(_ => _.Name, "The one you need")
);

container.RegisterType<AnotherTestObject>(
c => c
.SetValueProperty(_ => _.Name, "How did you get it??")
);

container.RegisterType<TestObject>(
c => c
.SetResolvedProperty(_ => _.A, "Test1")
.SetValueProperty(_ => _.B, "String value")
);

var testObject = container.Resolve<TestObject>();
Console.WriteLine(testObject.A.Name); // The one you need
Console.WriteLine(testObject.B); // String value
}
}

class TestObject
{
public AnotherTestObject A { get; set; }
public string B { get; set; }
}

public class AnotherTestObject
{
public string Name { get; set; }
}
}

We register AnotherTestObject twice: first time with name and  second – anonymous. For both registrations we specify value being set into property Name. After that we register TestObject with resolved property A. Our extension translates expression trees into various subtypes of InjectionMember but preserving type related information. This is funny but not new, we have already seen it in the previous post. What is really interesting is how can we use expression trees to describe constructor and method call. If we want to pass constant values everything is straightforward – just make another method in the interface, name it SetInitMethod and analyze expression in the similar way with SetResolvedProperty. But was if we want method arguments to be resolved from container during instance initialization? This is usual and widely used scenario. We need some auxiliary types to denote holes in our source expression so later this holes can be filled using values from container.

    /// <summary>
/// This type is used to make typed placeholders in expression trees that will be filled with actual values during resolution.
/// </summary>
public static class Param
{
internal static readonly MethodInfo ResolvedMethod = new Func<ResolvedParameterPlaceholder<int>>(Resolved<int>).Method.GetGenericMethodDefinition();
internal static readonly MethodInfo ResolvedWithNameMethod = new Func<string, ResolvedParameterPlaceholder<int>>(Resolved<int>).Method.GetGenericMethodDefinition();

public sealed class ResolvedParameterPlaceholder<T>
{
private ResolvedParameterPlaceholder() { }

public static implicit operator T(ResolvedParameterPlaceholder<T> p)
{
throw NoDynamicInvokation();
}
}

/// <summary>
/// Denotes placeholder for resolved value with specified type.
/// </summary>
/// <typeparam name="T">Type of target object</typeparam>
/// <returns>Resolution placeholder</returns>
public static ResolvedParameterPlaceholder<T> Resolved<T>()
{
throw NoDynamicInvokation();
}

/// <summary>
/// Denotes placeholder for resolved value with specified type and name.
/// </summary>
/// <typeparam name="T">Type of target object</typeparam>
/// <param name="name">Name of target object</param>
/// <returns>Resolution placeholder</returns>
public static ResolvedParameterPlaceholder<T> Resolved<T>(string name)
{
throw NoDynamicInvokation();
}

private static Exception NoDynamicInvokation()
{
return new InvalidOperationException("This operation is intended to be used in expression trees only");
}
}

ResolvedParameterPlaceholder type will act as placeholder (that’s why he has such weird name). It shouldn’t ever be created, we intended to use it only as marker in expression trees. Implicit conversion operator allows to use this type instead of any other actual types. Our analyzer will process usages of Param.Resolved separately and use ResolvedParameter instead of value. Nice and simple idea and it should also work for constructors. To select constructor we will use new expression + direct values and Param.Resolved.

using System;
using Microsoft.Practices.Unity;
using UStatic;

namespace UStaticTest
{
class Program
{
static void Main()
{
var container = new UnityContainer();

container.RegisterType<AnotherTestObject>(
c => c
.SetValueProperty(_ => _.Name, "AnotherTestObject")
);
container.RegisterType<YetAnotherTestObject>(
c => c
.SetValueProperty(_ => _.Name, "YetAnotherTestObject")
);

container.RegisterType<TestObject>(
c => c
.SetConstructor(() => new TestObject(Param.Resolved<YetAnotherTestObject>()))
.SetInitMethod(_ => _.Initialize(Param.Resolved<AnotherTestObject>()))
);

container.Resolve<TestObject>(); // Initialize: testObject.Name = AnotherTestObject, B = YetAnotherTestObject
}
}

class TestObject
{
public TestObject(YetAnotherTestObject obj)
{
B = obj;
}

public TestObject(YetAnotherTestObject obj, string text)
{
throw new InvalidOperationException("What's happen??");
}

public YetAnotherTestObject B { get; set; }

public void Initialize(AnotherTestObject testObject)
{
Console.WriteLine("Initialize: testObject.Name = {0}, B = {1}", testObject.Name, B.Name);
}
}

public class AnotherTestObject
{
public string Name { get; set; }
}

public class YetAnotherTestObject
{
public string Name { get; set; }
}
}

Complete source code of this project(I’ve named it UStatic) is avaiable here. As always any suggestions, constructive critisicm (and especially huge money donations :) ) are welcomed and appreciated.

вторник, 18 мая 2010 г.

Copy-And-Update in C#

Disclaimer: only for demonstration purposes :).

Immutability is natural for F# types; tuples, lists and records are immutable by default. Also records have special syntax “copy-and-update” that allows creation copy of existing record specifying only modified fields.

type DataObject = 
{ Id : int
Value : string
Object : DataObject2 }
and DataObject2 =
{ Price : decimal
PriceType : string }

let o1 = {Id = 100; Value = "Value"; Object = {Price = 10m; PriceType = "CleanPrice"}}
let o2 = {o1 with Id=500; Object = {o1.Object with Price = 500m} }
(*
val o1 : DataObject = {Id = 100;
Value = "Value";
Object = {Price = 10M;
PriceType = "CleanPrice";};}
val o2 : DataObject = {Id = 500;
Value = "Value";
Object = {Price = 500M;
PriceType = "CleanPrice";};}
*)

C# doesn't provide similar things, but using VS 2010 and combination of named and optional parameters we can achive almost the same level of expressiveness.

var o1 = new DataObject(100, "Value1", new DataObject2(10m, "CleanPrice"));
var o2 = o1.With(id: 500, obj: o1.Object.With(price: 500));
Console.WriteLine(o1);
Console.WriteLine(o2);
//Id = 100, Value = Value1, Object = (Price:10, PriceType=CleanPrice)
//Id = 500, Value = Value1, Object = (Price:500, PriceType=CleanPrice)

Pretty close to original, huh? Idea of implementation is very simple, we somehow need to distinguish missing values from entered. To achieve it we introduce struct Optional that will hold all input parameters

    public struct Optional<T>
{
public T Value;
public bool HasValue;

public Optional(T value)
{
HasValue = true;
Value = value;
}

public static implicit operator Optional<T>(T value)
{
return new Optional<T>(value);
}
public T ValueOrDefault(T defaultValue) { return HasValue ? Value : defaultValue; } }

With method in each class declare its arguments with type Optional<T> and default value default( Optional<T>). This is simple solution, all entered arguments shall be converted by implicit operator and thus have HasValue=true. Optional is struct because otherwise it is impossible to input null as user defined value, it shall be interpreted not as valid value but rather as missing one.

    public class DataObject
{
public int Id { get; private set; }
public string Value { get; private set; }
public DataObject2 Object { get; private set; }

public DataObject(int id, string value, DataObject2 o)
{
Id = id;
Value = value;
Object = o;
}

private DataObject()
{
}

public override string ToString()
{
return string.Format("Id = {0}, Value = {1}, Object = ({2})", Id, Value ?? "null", Object != null ? Object.ToString() : "null");
}

public DataObject With(
Optional<int> id = default(Optional<int>),
Optional<string> value = default(Optional<string>),
Optional<DataObject2> obj = default(Optional<DataObject2>)
)
{
return new DataObject
{
Id = id.ValueOrDefault(Id),
Value = value.ValueOrDefault(Value),
Object = obj.ValueOrDefault(Object)
};
}
}

public class DataObject2
{
public decimal Price { get; private set; }
public string PriceType { get; private set; }

public DataObject2(decimal price, string priceType)
{
Price = price;
PriceType = priceType;
}

private DataObject2()
{
}

public DataObject2 With(
Optional<decimal> price = default(Optional<decimal>),
Optional<string> priceType = default(Optional<string>)
)
{
return new DataObject2
{
Price = price.ValueOrDefault(Price),
PriceType = priceType.ValueOrDefault(PriceType)
};
}

public override string ToString()
{
return string.Format("Price:{0}, PriceType={1}", Price, PriceType ?? "null");
}
}

пятница, 26 марта 2010 г.

Fun with recursion

"To understand recursion you must understand recursion"

Recursion is an extremly useful tool in the toolbox of every developer. Many problems have recursive nature and thus best solved with recursion. Tree-like stucture is a very nice candidate for demonstration.

type Tree<'T> = Leaf of 'T | Node of Tree<'T> * Tree<'T>

Tree is recursively defined data-type, because it contains values that are Tree itself. A bunch of common operations for this tree (efficiency is dropped for benefit of simplicity).

let rec height = function
| Leaf _ -> 1
| Node(l, r) -> 1 + max (height l) (height r)
let rec sum = function
| Leaf v -> v
| Node(l, r) -> sum l + sum r
let rec toList = function
| Leaf(v) -> [v]
| Node(l, r) -> (toList l) @ (toList r)

All these operations follows the same pattern: Leaf is the base of recursion and Node case somehow combines results of recursive calls to left and right branches. Extract the pattern:

let rec processTree lF nF = function
| Leaf(v) -> lF v
| Node(l, r) -> nF (processTree lF nF l) (processTree lF nF r)

This function is the essence of tree processing order, other functions can be expressed with it.

let height_2 t = processTree (fun _ -> 1) (fun lr rr -> 1 + max lr rr) t
let sum_2 t = processTree id (+) t
let toList_2 t = processTree (fun v -> [v]) (@) t
let tree = 
Node(
Node(
Node(
Leaf(5),
Leaf(15)
),
Leaf(10)
),
Node(
Leaf(20),
Leaf(25)
)
)

printfn "%b" ((height tree) = (height_2 tree))
printfn "%b" ((sum tree) = (sum_2 tree))
printfn "%b" ((toList tree) = (toList_2 tree))
(*
true
true
true
*)

Here we have introduced higher order function that processes given tree in some order and returns the result. Thereby we removed boilerplate recursive code preserving only essential part.

In fact this is a simplified version of generic concept "fold" - well impacted paradigm in functional languages. Folds over lists are the most popular type of folds, but the concept can be spreaded over arbitraty algebraic data type (generalized version of fold is named catamorphism). Concerned persons can find a very nice review of this subject in a set of blog posts by Brian McNamara.

.NET BCL also contains fold for sequences (named Enumerable.Aggregate). We can take this function and, for example, create a generic processor for file system structure.

    public static class SimpleFileSystemWalker
{
public static T Walk<T>(string path, T seed, Func<FileInfo, T, T> fileProcessor, Func<DirectoryInfo, T, T> directoryProcessor)
{
return Directory.Exists(path)
? Walk(new DirectoryInfo(path), seed, fileProcessor, directoryProcessor)
: seed;
}

public static T Walk<T>(FileSystemInfo fsi, T seed, Func<FileInfo, T, T> fileProcessor, Func<DirectoryInfo, T, T> directoryProcessor)
{
if (fsi is FileInfo)
return fileProcessor((FileInfo)fsi, seed);
var di = (DirectoryInfo) fsi;
return directoryProcessor(
di,
di.EnumerateFileSystemInfos().Aggregate(seed, (acc, c) => Walk(c, acc, fileProcessor, directoryProcessor)));
}
}


Getting size of directory with this little helper.

            var size = SimpleFileSystemWalker.Walk(@"e:\Lame", 0L, (fi, acc) => acc + fi.Length, (di, acc) => acc);

File processor adds size of file to accumulator and directory processor does nothing - everything is clear and simple. However explicit recursion provides more control over traversing, for example we can skip directories that fits some criteria and current implementation lacks of this feature. We can add it for example by switching order of handlers (invoke directory processor before files) Then directory processor can somehow indicate whether we should go down or stop - for instance by returning bool value. This is possible solution but the code will look untidy: having business with Tuple.Create plus following checks with Item1 or Item2 - all these things makes me sad. More impressive version shall be the follwing - introduce additional parameter next of type delegate T Next(T) in directory processor. This parameter shall behave as continuation, direcory handler can invoke it inside its body to descent into the content of directory.

 public static class FileSystemWalker
{
public delegate TAcc FileInfoVisitor<TAcc>(FileInfo fileInfo, TAcc acc);
public delegate TAcc DirectoryInfoVisitor<TAcc>(DirectoryInfo directoryInfo, TAcc acc, Next<TAcc> next);
public delegate TAcc Next<TAcc>(TAcc acc);

public delegate void VoidFileInfoVisitor<TAcc>(FileInfo fileInfo, TAcc acc);
public delegate void VoidDirectoryInfoVisitor<TAcc>(DirectoryInfo directoryInfo, TAcc acc, VoidNext<TAcc> next);
public delegate void VoidNext<TAcc>(TAcc acc);

public static T Walk<T>(string path, T seed, FileInfoVisitor<T> fileVisitor, DirectoryInfoVisitor<T> directoryVisitor)
{
return Directory.Exists(path)
? Walk(new DirectoryInfo(path), seed, fileVisitor, directoryVisitor)
: seed;
}

public static void Walk<T>(string path, T seed, VoidFileInfoVisitor<T> fileVisitor, VoidDirectoryInfoVisitor<T> directoryVisitor)
{
if (Directory.Exists(path))
Walk(new DirectoryInfo(path), seed, fileVisitor, directoryVisitor);
}

private static T Walk<T>(FileSystemInfo fsi, T seed, FileInfoVisitor<T> fileVisitor, DirectoryInfoVisitor<T> directoryVisitor)
{
if (fsi is FileInfo)
{
return fileVisitor((FileInfo)fsi, seed);
}
var di = (DirectoryInfo) fsi;
return directoryVisitor(
di,
seed,
newSeed => di.EnumerateFileSystemInfos().Aggregate(
newSeed,
(current, nestedFsi) => Walk(nestedFsi, current, fileVisitor, directoryVisitor)
)
);
}


private static void Walk<T>(FileSystemInfo fsi, T seed, VoidFileInfoVisitor<T> fileVisitor, VoidDirectoryInfoVisitor<T> directoryVisitor)
{
if (fsi is FileInfo)
{
fileVisitor((FileInfo) fsi, seed);
}
else
{
var di = (DirectoryInfo) fsi;
directoryVisitor(
di,
seed,
newSeed =>
{
foreach (var nested in di.EnumerateFileSystemInfos())
{
Walk(nested, newSeed, fileVisitor, directoryVisitor);
}
}
);
}
}
}

We have added extra overload to Walk method that returns nothing and changes intermediate value only on the directory level. This feature is very handy in methods like Copy

        static void CopyFolder(string path, string destPath)
{
FileSystemWalker.Walk(
path,
destPath,
(fi, dir) => fi.CopyTo(Path.Combine(dir, fi.Name)),
(di, dir, next) =>
{
var newPath = Path.Combine(dir, di.Name);
if (!Directory.Exists(newPath))
Directory.CreateDirectory(newPath);

next(newPath);
}
);
}
static long CalculateSize(string path)
{
return FileSystemWalker.Walk(
path,
0L,
(fi, acc) => acc + fi.Length,
(di, acc, next) => next(acc)
);
}


Trampoline

Absence of explicit recursion makes possible modification of internal traverse code without changes in processing logic. For example we can update this code to be more stack-friendly by converting program to trampolined style. The idea behind trampoline is very simple: recursive call are replaced with return of function thunks. These thunks are invoked in loop so amount of stack frames remains the same.

delegate Rec Rec();
class Program
{
static void Print(int i)
{
if (i == 0)
return;
Console.WriteLine(i);
Print(i - 1);
}

static Rec TPrint(int i, Func<int, Rec> next)
{
if (i == 0)
return null;
Console.WriteLine(i);
return next(i - 1);
}

static void Main(string[] args)
{
// recursive version
Print(10);

// using trampoline
Rec run = null;
Func<int, Rec> next = null;

next = newV => run = () => TPrint(newV, next);
next(10);
while (run != null)
run = run();
}
}


Every iteration returns thunk to next step instead of making direct call. Let's see this step by step

Before method call: stack frame - Main method

t1

First iteration: Stack frame - TPrint


t2

After first iteration: Stack frame - Main method


t3

Second iteration: Stack frame - TPrint, but as we see there are no other calls to TPrint on the stack.

t4

Stack frame jumps up and down like a jumper on the trampoline.

Trampolined version of FileSystemWalker

    public static class TrampolinedFileSystemWalker
{
public delegate TAcc FileInfoVisitor<TAcc>(FileInfo fileInfo, TAcc acc);
public delegate void VoidFileInfoVisitor<TAcc>(FileInfo fileInfo, TAcc acc);
public delegate void DirectoryInfoVisitor<TAcc>(DirectoryInfo directoryInfo, TAcc acc, Next<TAcc> next);
public delegate void Next<in TAcc>(TAcc acc);

public static T Walk<T>(string path, T seed, FileInfoVisitor<T> fileVisitor, DirectoryInfoVisitor<T> directoryVisitor)
{
return Directory.Exists(path)
? Walk(new DirectoryInfo(path), seed, fileVisitor, directoryVisitor)
: seed;
}

private static T Walk<T>(FileSystemInfo fsi, T seed, FileInfoVisitor<T> fileVisitor, DirectoryInfoVisitor<T> directoryVisitor)
{
var value = seed;
var actions = new Queue<Action>();

Action<FileSystemInfo> processOne = null;
processOne = currFsi =>
{
if (currFsi is FileInfo)
{
value = fileVisitor((FileInfo) currFsi, value);
}
else
{
var di = (DirectoryInfo) currFsi;
directoryVisitor(
di,
value,
newValue =>
{
value = newValue;
foreach (var nested in di.EnumerateFileSystemInfos())
{
var n = nested;
actions.Enqueue(() => processOne(n));
}
}
);
}
};
actions.Enqueue(() => processOne(fsi));
while (actions.Any())
actions.Dequeue()();

return value;
}

public static void Walk<T>(string path, T seed, VoidFileInfoVisitor<T> fileVisitor, DirectoryInfoVisitor<T> directoryVisitor)
{
if (Directory.Exists(path))
Walk(new DirectoryInfo(path), seed, fileVisitor, directoryVisitor);
}

private static void Walk<T>(FileSystemInfo fsi, T seed, VoidFileInfoVisitor<T> fileVisitor, DirectoryInfoVisitor<T> directoryVisitor)
{
var actions = new Queue<Action>();

Action<FileSystemInfo, T> processOne = null;
processOne = (currFsi, value) =>
{
if (currFsi is FileInfo)
{
fileVisitor((FileInfo)currFsi, value);
}
else
{
var di = (DirectoryInfo)currFsi;
directoryVisitor(
di,
value,
newValue =>
{
foreach (var nested in di.EnumerateFileSystemInfos())
{
var n = nested;
actions.Enqueue(() => processOne(n, newValue));
}
}
);
}
};
actions.Enqueue(() => processOne(fsi, seed));
while (actions.Any())
actions.Dequeue()();
}
}

It is a bit more complex than previous sample, every call can lead to many recursive calls, so we replace single delegate with a queue of actions. Each step can put as many actions as it need and all calls shall be made one after another using fixed amount of stack frames.

static void CopyFolder(string path, string destPath)
{
FileSystemWalker.Walk(
path,
destPath,
(fi, dir) => fi.CopyTo(Path.Combine(dir, fi.Name)),
(di, dir, next) =>
{
var newPath = Path.Combine(dir, di.Name);
if (!Directory.Exists(newPath))
Directory.CreateDirectory(newPath);

next(newPath);
}
);
}

static void TCopyFolder(string path, string destPath)
{
TrampolinedFileSystemWalker.Walk(
path,
destPath,
(fi, dir) => fi.CopyTo(Path.Combine(dir, fi.Name)),
(di, dir, next) =>
{
var newPath = Path.Combine(dir, di.Name);
if (!Directory.Exists(newPath))
Directory.CreateDirectory(newPath);

next(newPath);
}
);
}

static long CalculateSize(string path)
{
return FileSystemWalker.Walk(
path,
0L,
(fi, acc) => acc + fi.Length,
(di, acc, next) => next(acc)
);
}
static long TCalculateSize(string path)
{
return TrampolinedFileSystemWalker.Walk(
path,
0L,
(fi, acc) => acc + fi.Length,
(di, acc, next) => next(acc)
);
}

Client code was isolated from details of traverse so it was unaffected by fundamental changes we made.

воскресенье, 7 марта 2010 г.

.NET 4.0 : Collectible assemblies

Since the first version .NET BCL gave developer a possibility to generate code in runtime via using types in System.Reflection.Emit (SRE) namespace. This feature was highly claimed in a various scopes, most well-known are:

  • Dynamic generation of proxy classes (applied in many AOP frameworks)
  • Creation of specialized implementations based on runtime data (for example mappers in ORMs)
  • Compilation and execution of different script languages

However all this magnificence has one “tiny” limitation, result assembly cannot be unloaded from the app domain. It stuck in the domain till the end of times (or the domain) thus becoming the source of memory leaks.

NET 2.0 introduces concept of dynamic methods that can be generated in runtime and referred by delegate. In contrast to dynamic assemblies dynamic methods can be collected by GC. But this solution was far for perfect: dynamic methods as follows from the name can define only methods (just code) and not types.

.NET 4.0 makes one step forward to new wonderful world, so without further delays let me introduce: Collectible Assemblies!

All details about their limitations and lifetime features are well described in MSDN article. So let’s turn to practice.

Declare a simple interface

    public interface IPrinter
{
void Print(string text);
}

Create a method that will generate the implementation with given AssemblyBuilderAccess



        private static Type CreatePrinterType(AssemblyBuilderAccess assemblyBuilderAccess)
{
var assembly = AppDomain.CurrentDomain.DefineDynamicAssembly(
new AssemblyName("transient_assembly"),
assemblyBuilderAccess
);

var module = assembly.DefineDynamicModule("transient");
var type = module.DefineType("ConsolePrinter");
type.AddInterfaceImplementation(typeof(IPrinter));
type.DefineDefaultConstructor(MethodAttributes.Public);

var method = type.DefineMethod(
"Print",
MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.Final,
typeof (void),
new[] {typeof (string)}
);

var il = method.GetILGenerator();
il.Emit(OpCodes.Ldarg_1);
il.Emit(OpCodes.Call, typeof(Console).GetMethod("WriteLine", new [] {typeof(string)}));
il.Emit(OpCodes.Ret);

return type.CreateType();
}


The only remaining thing we need for tests: little helper method to list all assemblies in domain



        private static void PrintAssemblies()
{
Console.WriteLine("===");
Console.WriteLine(string.Join(" ", AppDomain.CurrentDomain.GetAssemblies().Select(a => a.GetName().Name)));
}


Everything is ready, let's roll (all code should be compiled in Release and executed without debugger). Use good-old AssemblyBuilderAccess.Run



        static void Main(string[] args)
{
PrintAssemblies();
var t = CreatePrinterType(AssemblyBuilderAccess.Run);
PrintAssemblies();
var instance = (IPrinter)Activator.CreateInstance(t);
instance.Print("Hi from SRE!");

GC.Collect();
PrintAssemblies();
}
/*
===
mscorlib SRE System.Core System
===
mscorlib SRE System.Core System transient_assembly
Hi from SRE!
===
mscorlib SRE System.Core System transient_assembly
*/

Result is expected, transient assembly survived during garbage collection. A little twist… switch Run to RunAndCollect

        static void Main(string[] args)
{
PrintAssemblies();
var t = CreatePrinterType(AssemblyBuilderAccess.RunAndCollect);
PrintAssemblies();
var instance = (IPrinter)Activator.CreateInstance(t);
instance.Print("Hi from SRE!");

GC.Collect();
PrintAssemblies();
}
/*
===
mscorlib SRE System.Core System
===
mscorlib SRE System.Core System transient_assembly
Hi from SRE!
===
mscorlib SRE System.Core System
*/

Brilliant, isn't it? As soon as all references removed, transient assembly becomes eligible for garbage collection.

Note: MSDN article has a mistake in it:

Lifetime of Collectible Assemblies

The lifetime of a collectible dynamic assembly is controlled by the existence of references to the types it contains, and the objects that are created from those types. The common language runtime does not unload an assembly as long as one or more of the following exist (T is any type that is defined in the assembly): An instance of an array of T, or an instance of a generic collection that has T as one of its type arguments, even if that array or collection is empty.


The last sentence should be: An instance of an array of T, or an instance of any generic type (i.e. collection) that has T as one of its type arguments, even if that array or collection is empty.
        class A<T> { }
static void Main(string[] args)
{
PrintAssemblies();
var t = CreatePrinterType(AssemblyBuilderAccess.RunAndCollect);
var at = typeof (A<>).MakeGenericType(t);
PrintAssemblies();

GC.Collect();
PrintAssemblies();
Console.WriteLine(at);
}
/*
===
mscorlib SRE System.Core System
===
mscorlib SRE System.Core System transient_assembly
===
mscorlib SRE System.Core System transient_assembly
SRE.Program+A`1[ConsolePrinter]
*/

воскресенье, 21 февраля 2010 г.

Extending Unity configuration.

For the first time I’ve used DI container 5 years ago (it was Spring for Java). During the first experience I was greatly impressed with the required style of design: component needs to do only what outer world expect from him. All other things, like creating or locating dependencies should be put outside the component. This is quite obvious but abidance of these simple rules brings a number of valuable benefits:

  • If component does only what it is responsible to do then the code decreases in size and become easier to understand
  • All dependencies of component can be determined from its public interface (through properties, constructor parameters etc)
  • Level of potential reusability increases due to low coupling
  • Testability increases especially with application of tools like RhinoMocks and Moq

Unity is a simple and lightweight DI container for .NET. It allows defining interconnections between components both in XML and using API of IUnityContainer. In this post I’d like to show the idea how configuration mechanism can be extended using possibilities of C# 3.0.

Sample classes and interfaces:
public interface IMyComponent
{
void Run();
}

public interface ILogger
{
void LogInfo(string format, params object[] args);
}


public class MyComponent : IMyComponent
{
public string Text { get; set; }
public ILogger Logger { get; set; }
public void Run()
{
Logger.LogInfo(Text);
}
}

public class ConsoleLogger : ILogger
{
public void LogInfo(string format, params object[] args)
{
Console.WriteLine(format, args);
}
}

As we can see MyComponent class is decoupled from concrete implementation of ILogger so is can be tested with ILogger stub, reused with other type of logger and so on. Let’s create a code that will wire up all these components together.

1. Create UnityContainer and register all types in it

var container = new UnityContainer()
.RegisterType<IMyComponent, MyComponent>(
new InjectionMember[]
{
new InjectionProperty("Logger", new ResolvedParameter(typeof (ILogger),"Logger")),
new InjectionProperty("Text", "DataSource=...")
}
)
.RegisterType<ILogger, ConsoleLogger>("Logger");

For this sample I've used beta release of Unity – Feb 2010, in the older versions configuration of injected members is available only through calling ConfigureInjectionFor with InjectedMembers extension.

2. Instantiate MyComponent and run operation

var myComponent = container.Resolve<IMyComponent>();
myComponent.Run();

Line "DataSource=…" should appear in console.

Everything seems to be fine, but… IMHO this version of code has few flaws. First: property is referred via string name and this is very error prone. One occasional rename operation and BOOM!!! Second inconvenience is that property type should be set explicitly. This is annoying and unsafe approach, developer can change type of property but DI container will still try to inject dependent object relying on the old type. Let's add that both of mentioned errors are invisible to compiler and reveal itself only in runtime.

Time to make some improvements. C# 3.0 already provides ways to refer type members in type-safe way via using expression trees. We can apply them both to define target property and to get its type. This version will be much more resistant to errors because of compiler control.

In the beginning - some auxiliary types

/// <summary>
/// Accumulator of type-related settings
/// </summary>
/// <typeparam name="T"></typeparam>
public interface ITypeConfigurator<T>
{
ITypeConfigurator<T> SetName(string name);
ITypeConfigurator<T> SetLifetimeManager(LifetimeManager lifetimeManager);
ITypeConfigurator<T> SetResolvedProperty<TRes>(Expression<Func<T, TRes>> expr);
ITypeConfigurator<T> SetResolvedProperty<TRes>(Expression<Func<T, TRes>> expr, string objectName);
ITypeConfigurator<T> SetValueProperty<TRes>(Expression<Func<T, TRes>> expr, TRes value);
}

public class TypeConfigurator<T> : ITypeConfigurator<T>
{
public TypeConfigurator()
{
InjectionMembers = new List<InjectionMember>();
LifetimeManager = new ContainerControlledLifetimeManager(); // default value
}

public string Name { get; private set; }
public LifetimeManager LifetimeManager { get; private set; }
public List<InjectionMember> InjectionMembers { get; private set; }

ITypeConfigurator<T> ITypeConfigurator<T>.SetName(string name)
{
Name = name;
return this;
}

ITypeConfigurator<T> ITypeConfigurator<T>.SetLifetimeManager(LifetimeManager lifetimeManager)
{
LifetimeManager = lifetimeManager;
return this;
}

ITypeConfigurator<T> ITypeConfigurator<T>.SetResolvedProperty<TRes>(Expression<Func<T, TRes>> expr)
{
return AddResolvedProperty(expr, null);
}

ITypeConfigurator<T> ITypeConfigurator<T>.SetResolvedProperty<TRes>(Expression<Func<T, TRes>> expr, string objectName)
{
return AddResolvedProperty(expr, objectName);
}

private ITypeConfigurator<T> AddResolvedProperty<TRes>(Expression<Func<T, TRes>> expr, string objectName)
{
var property = GetPropertyInfo(expr);
var propertyValue = string.IsNullOrEmpty(objectName)
? new ResolvedParameter<TRes>()
: new ResolvedParameter<TRes>(objectName);
InjectionMembers.Add(new InjectionProperty(property.Name, propertyValue));
return this;
}

ITypeConfigurator<T> ITypeConfigurator<T>.SetValueProperty<TRes>(Expression<Func<T, TRes>> expr, TRes value)
{
var property = GetPropertyInfo(expr);
InjectionMembers.Add(new InjectionProperty(property.Name, value));
return this;
}

private static PropertyInfo GetPropertyInfo(LambdaExpression expr)
{
var memberExpression = expr.Body as MemberExpression;
if (memberExpression == null)
throw new ArgumentException("Simple member expression expected");

var propertyInfo = memberExpression.Member as PropertyInfo;
if (propertyInfo == null)
throw new ArgumentException("Property access expression expected");
return propertyInfo;
}
}

Entry point to improved configuration mechanism can be defined as an extension method for IUnityContainer interface.

public static class UnityContainerExtensions
{
/// <summary>
/// Gathers type information and applies it to provided container.
/// </summary>
/// <remarks>
/// I have used delegate <see cref="configurator"/> in interface for simplification
/// because otherwise I need to create bunch of overloads
/// RegisterType(name, SetLifetimeManager...)
/// RegisterType(name, ...)
/// RegisterType(...)
/// RegisterType(SetLifetimeManager)
/// In current version in case of need it is possible to set SetLifetimeManager and SetName with <see cref="ITypeConfigurator{T}.SetName"/>
/// or <see cref="ITypeConfigurator{T}.SetLifetimeManager"/> methods.
/// </remarks>
public static IUnityContainer RegisterType<TFrom, TTo>(
this IUnityContainer container,
Action<ITypeConfigurator<TTo>> configurator
) where TTo : TFrom
{
var typeConfigurator = new TypeConfigurator<TTo>();
// configurator will accumulate all settings defined by user
configurator(typeConfigurator);

// collected settings are applied to actual container
return container.RegisterType<TFrom, TTo>(
typeConfigurator.Name,
typeConfigurator.LifetimeManager,
typeConfigurator.InjectionMembers.ToArray()
);
}
}

And finally, advanced configurator in action:

var container = new UnityContainer()
.RegisterType<IMyComponent, MyComponent>(
c =>
c
.SetResolvedProperty(_ => _.Logger, "Logger")
.SetValueProperty(_ => _.Text, "DataSource=..")
)
.RegisterType<ILogger, ConsoleLogger>("Logger");

var myComponent = container.Resolve<IMyComponent>();
myComponent.Run();


Summary: unnecesary stuff removed, error-resistance: +10, additional skills: compile-time checks over property names, automatic inference of property types

среда, 17 февраля 2010 г.

Co/Contravariance for .NET 2.0+

CLR supports generic variance for generic interfaces and delegates since version 2.0.

ECMA 335:

The CLI supports covariance and contravariance of generic parameters, but only in the signatures of interfaces and delegate classes. Suppose we have a generic interface, which is covariant in its one generic parameter; e.g., IA`1<+T>. Then all instantiations satisfy IA`1<GenArgB> := IA`1<GenArgA>, so long as GenArgB := GenArgA using the notion from assignment compatibility. So, for example, an instance of type IA`1<string> can be assigned to a local of type type IA`1<object>.

Generic contravariance operates in the opposite sense: supposing that we have a contravariant interface IB`1<-T>, then IB`1<GenArgB> := IB`1<GenArgA>, so long as GenArgA := GenArgB.

in spite of this, co/contravariance features  were only partially exposed for the users of mainstream languages. C# 2.0 add support only for covariance and contravariance in delegates.  C# 4.0 makes one step further: both interfaces and delegates are supported and now it is possible to annotate generic parameter to be either covariant (out) or contravariant (in) and compiler will verify that all usages of this parameter are correct corresponding to the annotation.

For example:

public interface IMyComparer<in T>
{
// contravariant generic parameter
int Compare(T a, T b);
}

public interface IFactory<out T>
{
// covariant generic parameter
T Create();
}

public class MyComparer<T> : IMyComparer<T>
{
public int Compare(T a, T b)
{
return 0;
}
}

public class Factory<T> : IFactory<T>
{
public T Create()
{
return default(T);
}
}

// usage

IMyComparer<string> s = new MyComparer<object>();
IFactory<object> p = new Factory<string>();

Very nice feature! And it doesn’t require .NET 4.0 for execution, runtime already supports variance and C# compiler makes all remaining job.

Note:, all standard interfaces (IEnumerable<T>, IEnumerator<T>, IQueryable<T>, IGrouping<TK, TV>, IEqualityComparer<T>, IComparer<T>, IComparable<T> ) and delegates (Action<>, Func<T>, Predicate<T>, Comparison<T>, Converter<TIn, TOut>) shall not be accessible, since annotated versions are located in 4.0 assemblies.

Other compiler features that are accessible from VS 2010 for .NET 2.0+

  • optional parameters
  • named parameters
class Program
{
static void Main(string[] args)
{
Run(b : "value", a : 10);
}

public static void Run(int a, string b)
{
Console.WriteLine("a = {0}, b = {1}", a, b);
}
}
 
GeekySpeaky: Submit Your Site!