2

I have a method that looks something like this:

public static T GenerateProxy<T>(params object[] ctorArgs)
{
    return proxyGenerator.CreateProxy(typeof(T), ctorArgs);
}

Basically, it's calling the appropriate constructor based on the type T and whatever arguments I provide to find a matching constructor. This works, but if the constructor changes, I don't get any compile-time errors if I change the number of arguments a constructor changes. I found a nice utility method that uses an Expression to get the constructor arguments like so:

public static object[] GetCTorArgumentsFromSelector<T>(Expression<Func<T>> ctorCall) where T : class
{
    if (ctorCall == null) throw new ArgumentNullException("ctorCall");

    var newCall = ctorCall.Body as NewExpression;
    if (newCall == null)
    {
        throw new ArgumentException("Not a constructor call.", "ctorCall");
    }

    int argumentCount = newCall.Arguments.Count;

    var ctorArgs = new object[argumentCount];
    for (int i = 0; i < ctorArgs.Length; i++)
    {
        var param = newCall.Arguments[i] as ConstantExpression;
        if (param == null)
            throw new ArgumentException("You may only place constant values in calls to the constructor.");

        ctorArgs[i] = param.Value;
    }

    return ctorArgs;
}

So it can be used like so:

SomeClass arg = new SomeClass();
var ctorArgs = GetCTorArgumentsFromSelector(() => MyClass(arg));
var proxy = GenerateProxy<MyClass>(ctorArgs);

...which would be nice and strongly typed. So...since I don't know a whole lot about Expressions, I'm wondering if the limitation of only using constants can be worked around in any way. My example above wouldn't work because arg isn't a constant, but it would be nice to use it this way.

I think I understand why the limitation exists, but I was hoping someone else might have a good idea of an alternative method here. Thanks in advance.

Edit - So, after some more searching, it seems I can replace ConstantExpression with MemberExpression, then compile and invoke it using the method found in the answer here...but I have no idea what the ramifications of this are.

Community
  • 1
  • 1
Ocelot20
  • 10,510
  • 11
  • 55
  • 96
  • First ramification I can think of is compiling expression tree is expensive operation. (Navigating it is alright, so grabbing the Value in constant expression is fine). But as they all say, premature optimisation is one of the 7 sins, use it, profile it, and then decide if it's too slow. – Sleeper Smith Apr 19 '13 at 07:04
  • I don't get why it needs to be all so fancy and complicated? Wouldn't holding on to the constructor delegate and invoking that solve all the problems? Instead of "Expression> ctorCall", do "Func ctorCall", then just ctorCall() to get your class? If you are grabbing constructor from one class and stuffing it into another, you won't get compile time safety anyway. – Sleeper Smith Apr 19 '13 at 07:06

0 Answers0