Anyone who’s ever done office integration has come across a method definition like so:
object Run(object Macro, object Arg1, object Arg2, …, object Arg30);
if you're working in VB it’s not such an issue, and rumor has it that it’s that C# 4 will also solve the problem of code such as:
Run(“…”, Type.Missing, Type.Missing,/*28 more times*/ …, Type.Missing);
But for everyone else, you can avoid the extra typing with an extension method and dynamic lambda expressions. For example with:
public static class OfficeHelpers
{
private static MemberInfo missingMemberInfo = typeof(Type).GetMembers().Where(mi => mi.Name == "Missing").Single();
private static MethodInfo runMethodInfo = typeof(_Application).GetMethod("Run");
private static ParameterExpression macroNameParamExp = Expression.Parameter(typeof(string), "macroName");
private static ParameterExpression argsParamExp = Expression.Parameter(typeof(object[]), "args");
public static object Run(this Application App, string macroName, params object[] args)
{
var argsExprs = GenerateArgs(runMethodInfo, macroName, args);
var callExpr = Expression.Call(Expression.Constant(App), runMethodInfo, argsExprs);
var paramExprs = new ParameterExpression[] { macroNameParamExp, argsParamExp };
var lambda = Expression.Lambda>(callExpr, paramExprs);
return lambda.Compile().Invoke(macroName, args);
}
private static IEnumerable<Expression> GenerateArgs(MethodInfo runfuncMI, string macroName, object[] args)
{
yield return macroNameParamExp;
for (int ii = 0; ii < args.Length; ii++)
yield return BinaryExpression.ArrayIndex(argsParamExp, Expression.Constant(ii, typeof(int)));
for (int ii = 0; ii < runfuncMI.GetParameters().Length - args.Length - 1; ii++)
yield return Expression.MakeMemberAccess(null, missingMemberInfo);
}
a call to
OfficeHelpers.Run("…", arg1,arg2,arg3);
will generate and execute an expression like so:
(macroName, args) => RunFuncTest(macroName, args[0], args[1], args[2], Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing)
A few months ago, over the winter holiday, I put together a Linq provider for the Kdb+ database. The folks at KX systems have graciously provided a place to host the code, which you can find at https://code.kx.com/svn/contrib/sweinstein/linq2kdbplus. Use anonymous/anonymous for access.
As of now the list of the unimplemented items is considerably longer than implemented features.
What works
- Basic projections / Selects (map)
- Basic restrictions / Wheres (filter)
- code generation to create strongly typed representations of a Kdb database
Still remaining to implemented
- Joins
- Orderbys
- Grouping
- Aggregates and other functions/method calls
- Kdb+ columns with array types
- Code generation support for Kdb+ user functions
A few notes on the code
The heavy lifting of transforming the expression trees done via IQToolkit The unit tests uses xUnit.Net The code generation uses T4 and requires the T4 Toolbox - run SetupCodeGen.ps1 to have the correct paths placed in the registry
Linq2Kdb+ was developed on .Net 3.5SP1 and Kdb+ 2.5 - for other versions YMMV. Feedback welcome.
The benefits of using an inversion of control container for simplifying the task of initializing an object graph have been well covered. But the benefits of using an IoC container for simplifying object cleanup are not as well publicized, and is a feature that I've grown to really like taking advantage of.
The other night, at an Alt.Net Meetup on dependency injection/inversion of control I found myself being only person in the room enthusiastic about this.
The core of the problem is that objects that require cleanup, (ie implement IDisposable) can infect object hierarchies - any class with a has-a relationship to the IDisposable class really needs implement IDisposable itself. If you're not careful, you can easily end up with tens of classes that have the nearly-all-ceremony Dispose() methods that do nothing but cleanup their children.
The cleanest solution for this problem is to move the member level containment to method level and wrap the use of the disposable in a using statement. But when that isn't a viable option the next best option is to move to dependency injection - if your class didn't create a disposable object, it can't be responsible for cleaning it up.
Of course, at some point the objects do need to be disposed of, in the simplest way to do that is to use a container, such as autofac, which supports both nested containers and object cleanup.