I am having a little trouble with something I am working on. I initially created a generic layer that sits between my business objects and the data access layer which is working fine. I then recently read about something called Expression Trees which is apparently more efficient and has proven to be so as I swapped Activator.CreateInstance() with an expression and has improved my generic layer exponentially.
I am still doing some reading about the whole area (Expressions) but I came across some code which I want to try making generic. At the moment, you have to pass in a concrete type such as a string, int, decimal etc. I was this bit to be generic. I Tried a couple of things but failed. The bit I want generic is Action, I don't want to pass in a string I want to be able to pass in the type of the property generically, i.e. typeof(T).GetProperty("Forename").PropertyType. Is this possible? Was thinking of doing a switch statement which is kinda foo bar.
Thanks in advance, Onam.
public class TTT<T> where T : new()
{
public void Do(object t)
{
MethodInfo info = typeof(T).GetProperty("Forename").GetSetMethod();
ParameterExpression param = Expression.Parameter(typeof(string), "val");
MethodCallExpression call = Expression.Call(Expression.Constant(t), info,
new ParameterExpression[] { param });
Action<string> action = Expression.Lambda<Action<string>>(call, param).Compile();
action("hi");
}
}
First, note that this is not a good way to do this; there is no performance advantage if you are building an Expression per-call, and then Compile()-ing it, and then invoking it. Reflection would be faster. If you need performance, look at a library such as "FastMember", where this would just be:
var accessor = TypeAccessor.Create(typeof(T));
accessor[target, "Forename"] = value;
(where that is fully optimized via meta-programming and automatic caching)
If you want the type to be dynamic, then there are two options:
type it using Expression.GetActionType and use DynamicInvoke - really bad performance (hint: don't do this)
type it as Action<object> and do a cast inside the expression (fine)
So something like:
using System;
using System.Linq.Expressions;
using System.Reflection;
class Foo
{
public string Forename {get;set;}
}
class Test<T>
{
public void Do(object target, object value)
{
var obj = Expression.Constant(target, typeof(T));
var member = Expression.PropertyOrField(obj, "Forename");
var param = Expression.Parameter(typeof(object));
Type type;
switch(member.Member.MemberType)
{
case MemberTypes.Field:
type = ((FieldInfo)member.Member).FieldType; break;
case MemberTypes.Property:
type = ((PropertyInfo)member.Member).PropertyType; break;
default:
throw new NotSupportedException(member.Member.MemberType.ToString());
}
var body = Expression.Assign(member, Expression.Convert(param, type));
var lambda = Expression.Lambda<Action<object>>(body, param);
lambda.Compile()(value);
}
}
static class Program
{
static void Main()
{
var obj = new Foo();
new Test<Foo>().Do(obj, "abc");
Console.WriteLine(obj.Forename);
}
}
Related
The title is kind of obscure. What I want to know is if this is possible:
string typeName = <read type name from somwhere>;
Type myType = Type.GetType(typeName);
MyGenericClass<myType> myGenericClass = new MyGenericClass<myType>();
Obviously, MyGenericClass is described as:
public class MyGenericClass<T>
Right now, the compiler complains that 'The type or namespace 'myType' could not be found." There has got to be a way to do this.
You can't do this without reflection. However, you can do it with reflection. Here's a complete example:
using System;
using System.Reflection;
public class Generic<T>
{
public Generic()
{
Console.WriteLine("T={0}", typeof(T));
}
}
class Test
{
static void Main()
{
string typeName = "System.String";
Type typeArgument = Type.GetType(typeName);
Type genericClass = typeof(Generic<>);
// MakeGenericType is badly named
Type constructedClass = genericClass.MakeGenericType(typeArgument);
object created = Activator.CreateInstance(constructedClass);
}
}
Note: if your generic class accepts multiple types, you must include the commas when you omit the type names, for example:
Type genericClass = typeof(IReadOnlyDictionary<,>);
Type constructedClass = genericClass.MakeGenericType(typeArgument1, typeArgument2);
Unfortunately no there is not. Generic arguments must be resolvable at Compile time as either 1) a valid type or 2) another generic parameter. There is no way to create generic instances based on runtime values without the big hammer of using reflection.
Some additional how to run with scissors code. Suppose you have a class similar to
public class Encoder() {
public void Markdown(IEnumerable<FooContent> contents) { do magic }
public void Markdown(IEnumerable<BarContent> contents) { do magic2 }
}
Suppose at runtime you have a FooContent
If you were able to bind at compile time you would want
var fooContents = new List<FooContent>(fooContent)
new Encoder().Markdown(fooContents)
However you cannot do this at runtime. To do this at runtime you would do along the lines of:
var listType = typeof(List<>).MakeGenericType(myType);
var dynamicList = Activator.CreateInstance(listType);
((IList)dynamicList).Add(fooContent);
To dynamically invoke Markdown(IEnumerable<FooContent> contents)
new Encoder().Markdown( (dynamic) dynamicList)
Note the usage of dynamic in the method call. At runtime dynamicList will be List<FooContent> (additionally also being IEnumerable<FooContent>) since even usage of dynamic is still rooted to a strongly typed language the run time binder will select the appropriate Markdown method. If there is no exact type matches, it will look for an object parameter method and if neither match a runtime binder exception will be raised alerting that no method matches.
The obvious draw back to this approach is a huge loss of type safety at compile time. Nevertheless code along these lines will let you operate in a very dynamic sense that at runtime is still fully typed as you expect it to be.
My requirements were slightly different, but will hopefully help someone. I needed to read type from a config and instantiate the generic type dynamically.
namespace GenericTest
{
public class Item
{
}
}
namespace GenericTest
{
public class GenericClass<T>
{
}
}
Finally, here is how you call it. Define the type with a backtick.
var t = Type.GetType("GenericTest.GenericClass`1[[GenericTest.Item, GenericTest]], GenericTest");
var a = Activator.CreateInstance(t);
If you know what types will be passed you can do this without reflection. A switch statement would work. Obviously, this would only work in a limited number of cases, but it'll be much faster than reflection.
public class Type1 { }
public class Type2 { }
public class Generic<T> { }
public class Program
{
public static void Main()
{
var typeName = nameof(Type1);
switch (typeName)
{
case nameof(Type1):
var type1 = new Generic<Type1>();
// do something
break;
case nameof(Type2):
var type2 = new Generic<Type2>();
// do something
break;
}
}
}
In this snippet I want to show how to create and use a dynamically created list. For example, I'm adding to the dynamic list here.
void AddValue<T>(object targetList, T valueToAdd)
{
var addMethod = targetList.GetType().GetMethod("Add");
addMethod.Invoke(targetList, new[] { valueToAdd } as object[]);
}
var listType = typeof(List<>).MakeGenericType(new[] { dynamicType }); // dynamicType is the type you want
var list = Activator.CreateInstance(listType);
AddValue(list, 5);
Similarly you can invoke any other method on the list.
The title is kind of obscure. What I want to know is if this is possible:
string typeName = <read type name from somwhere>;
Type myType = Type.GetType(typeName);
MyGenericClass<myType> myGenericClass = new MyGenericClass<myType>();
Obviously, MyGenericClass is described as:
public class MyGenericClass<T>
Right now, the compiler complains that 'The type or namespace 'myType' could not be found." There has got to be a way to do this.
You can't do this without reflection. However, you can do it with reflection. Here's a complete example:
using System;
using System.Reflection;
public class Generic<T>
{
public Generic()
{
Console.WriteLine("T={0}", typeof(T));
}
}
class Test
{
static void Main()
{
string typeName = "System.String";
Type typeArgument = Type.GetType(typeName);
Type genericClass = typeof(Generic<>);
// MakeGenericType is badly named
Type constructedClass = genericClass.MakeGenericType(typeArgument);
object created = Activator.CreateInstance(constructedClass);
}
}
Note: if your generic class accepts multiple types, you must include the commas when you omit the type names, for example:
Type genericClass = typeof(IReadOnlyDictionary<,>);
Type constructedClass = genericClass.MakeGenericType(typeArgument1, typeArgument2);
Unfortunately no there is not. Generic arguments must be resolvable at Compile time as either 1) a valid type or 2) another generic parameter. There is no way to create generic instances based on runtime values without the big hammer of using reflection.
Some additional how to run with scissors code. Suppose you have a class similar to
public class Encoder() {
public void Markdown(IEnumerable<FooContent> contents) { do magic }
public void Markdown(IEnumerable<BarContent> contents) { do magic2 }
}
Suppose at runtime you have a FooContent
If you were able to bind at compile time you would want
var fooContents = new List<FooContent>(fooContent)
new Encoder().Markdown(fooContents)
However you cannot do this at runtime. To do this at runtime you would do along the lines of:
var listType = typeof(List<>).MakeGenericType(myType);
var dynamicList = Activator.CreateInstance(listType);
((IList)dynamicList).Add(fooContent);
To dynamically invoke Markdown(IEnumerable<FooContent> contents)
new Encoder().Markdown( (dynamic) dynamicList)
Note the usage of dynamic in the method call. At runtime dynamicList will be List<FooContent> (additionally also being IEnumerable<FooContent>) since even usage of dynamic is still rooted to a strongly typed language the run time binder will select the appropriate Markdown method. If there is no exact type matches, it will look for an object parameter method and if neither match a runtime binder exception will be raised alerting that no method matches.
The obvious draw back to this approach is a huge loss of type safety at compile time. Nevertheless code along these lines will let you operate in a very dynamic sense that at runtime is still fully typed as you expect it to be.
My requirements were slightly different, but will hopefully help someone. I needed to read type from a config and instantiate the generic type dynamically.
namespace GenericTest
{
public class Item
{
}
}
namespace GenericTest
{
public class GenericClass<T>
{
}
}
Finally, here is how you call it. Define the type with a backtick.
var t = Type.GetType("GenericTest.GenericClass`1[[GenericTest.Item, GenericTest]], GenericTest");
var a = Activator.CreateInstance(t);
If you know what types will be passed you can do this without reflection. A switch statement would work. Obviously, this would only work in a limited number of cases, but it'll be much faster than reflection.
public class Type1 { }
public class Type2 { }
public class Generic<T> { }
public class Program
{
public static void Main()
{
var typeName = nameof(Type1);
switch (typeName)
{
case nameof(Type1):
var type1 = new Generic<Type1>();
// do something
break;
case nameof(Type2):
var type2 = new Generic<Type2>();
// do something
break;
}
}
}
In this snippet I want to show how to create and use a dynamically created list. For example, I'm adding to the dynamic list here.
void AddValue<T>(object targetList, T valueToAdd)
{
var addMethod = targetList.GetType().GetMethod("Add");
addMethod.Invoke(targetList, new[] { valueToAdd } as object[]);
}
var listType = typeof(List<>).MakeGenericType(new[] { dynamicType }); // dynamicType is the type you want
var list = Activator.CreateInstance(listType);
AddValue(list, 5);
Similarly you can invoke any other method on the list.
I have a list of objects ListOfObjects that are all of the same type, but the specific type is not known (however, I do know all the possible types). There are
many possible types. Each object has the property Name, which is a string of its type. I want do something like the following:
foreach (object elements in ListOfObjects)
{
// Some code here that casts elements into the specific type and pass it into another function
}
I know one way to do this is to use a switch case statement
switch (ListOfObjects[0].Name)
{
case "Type1":
//cast into Type1 and pass into function
case "Type2":
//cast into Type2 and pass into function
default:
//something
break;
}
Is there a cleaner way to do this? Is is possible to store the possible Types in a dictionary and cast from that dictionary?
Pattern Matching
To start I want to present the use of pattern matching in switch statements to work with different types, as follows:
public static double ComputeAreaModernSwitch(object shape)
{
switch (shape)
{
case Square s:
return s.Side * s.Side;
case Circle c:
return c.Radius * c.Radius * Math.PI;
case Rectangle r:
return r.Height * r.Length;
default:
throw new ArgumentException(
message: "shape is not a recognized shape",
paramName: nameof(shape));
}
}
Example taken from Pattern Matching - C# Guide.
Type Dictionary
With that out of the way, yes, you can write a dictionary... the trouble will be on the type of the items.
We can do this:
Dictionary<Type, Action<object>> dictionary;
// (initialize and populate somewhere else) ...
if (dictionary.TryGetValue(element.GetType(), out var action))
{
action(element);
}
However, here you have to use Action<object> because we need to give a type to the items (and no, we can't say Action<?> - well, we can do Action<dynamic> but you cannot cast Action<someType> to Action<dynamic>), forcing you to cast inside the called method.
We can argue that a cast is a way to tell the compiler that we know something it does not. In this case that we know that that object is actually of a given type.
We could do a bit better/worse, depending on how you look at it...
Dictionary<Type, Delegate> dictionary;
// (initialize and populate somewhere else) ...
if (dictionary.TryGetValue(element.GetType(), out var #delegate))
{
#delegate.DynamicInvoke(element);
}
This is effectively late binding. We do not know the types at compile time... as developer you must ensure you provide a delegate of the correct type. However, if we are already enforcing knowledge that the compiler is unaware of, then this could be acceptable.
We can make a helper method to make it easier:
void SetMethod<T>(Action<T> action)
{
dictionary[typeof(T)] = action;
}
Here the compiler can check the type for the method is correct. Yet, from the point of view of the compiler this information is lost (not available) when you consume the dictionary. It is a kind of type erasure if you will.
Dynamic
Now, if we are forgoing types, we could use dynamic following good answer by TheGeneral.
Addendum: Calling a known method (with MethodInfo)
You can call a method by its name, for example, if you have the following:
class Helper
{
public static void Method(T input)
{
Console.WriteLine(input.GetType());
}
}
You can do this:
var methodInfo = typeof(Helper).GetMethod("Method");
// ...
methodInfo.Invoke(null, new object[]{element});
You could then put all your methods in a helper class, and find them by the name (which you could derive from the name of the type).
If you want to call a known method that has a generic parameter, you can use MethodInfo. We need to be aware of whatever or not the method is static, and whatever or not the generic argument is part of the method definition or the declaring type definition...
On one hand, if you have something like this:
class Helper<T>
{
public static void Method(T input)
{
Console.WriteLine(input.GetType());
}
}
You can do this:
var helperType = typeof(Helper<>);
// ...
var specificMethodInfo = helperType.MakeGenericType(element.GetType()).GetMethod("Method");
specificMethodInfo.Invoke(null, new object[]{element});
On the other hand, if you have this:
class Helper
{
public static void Method<T>(T input)
{
Console.WriteLine(input.GetType());
}
}
You can do this:
var methodInfo = typeof(Helper).GetMethod("Method");
// ...
var specificMethodInfo = methodInfo.MakeGenericMethod(element.GetType());
specificMethodInfo.Invoke(null, new object[]{element});
Note: I pass null as first parameter to invoke. That is the instance on which I am calling the method. None, because they are static. If they aren't then you need an instance... you could try creating one with Activator.CreateInstance, for example.
Addendum: Finding what to call (Type Discovery)
Perhaps you have disparate method to call (they are not the same but with different generic argument), but you do not want to have the trouble of populate the dictionary by hand.
That is where Type Discovery comes in.
To begin with, I suggest to use an attribute, for example:
[AttributeUsage(AttributeTargets.Method)]
public sealed class DataHandlerAttribute : Attribute { }
Then we need a list of the types where we will search. If we will search on a known assembly we could do this:
var assembly = typeof(KnownType).GetTypeInfo().Assembly;
var types = assembly.GetTypes();
Note: if your target platform does not support this (.NET Standard 1.0 to 1.4), you will have to hand code the list of types.
Next, we need a predicate to check if a given type is one of the ones in which we are interested:
bool IsDataHandlerMethod(MethodInfo methodInfo)
{
var dataHandlerAttributes = return (DataHandlerAttribute[])item.GetCustomAttributes(typeof(DataHandlerAttribute), true);
if (attributes == null || attributes.Length == 0)
{
return false;
}
if (methodInfo.DeclaringType != null)
{
return false;
}
if (methodInfo.ReturnTpye != typeof(void))
{
return false;
}
var parameters = methodInfo.GetParameters();
if (parameters.Length != 1)
{
return false;
}
if (paramters[0].IsByRef || paramters[0].IsOut)
{
return false;
}
return true;
}
And a method to convert them into delegates:
(Type, Delegate) GetTypeDelegatePair(MethodInfo methodInfo)
{
var parameters = methodInfo.GetParameters();
var parameterType = parameters[0].ParameterType;
var parameterTypeArray = new []{parameterType};
var delegateType = typeof(Action<>).MakeGenericType(parameterTypeArray);
var target = null;
if (!methodInfo.IsStatic)
{
var declaringType = methodInfo.DeclaringType;
target = instance = Activator.CreateInstance(declaringType);
}
return (parameterType, methodInfo.CreateDelegate(delegateType, target));
}
And now we can do this:
var dataHandlers = types
.SelectMany(t => t.GetTypeInfo().GetMethods())
.Where(IsDataHandlerMethod)
.Select(GetTypeDelegatePair);
And we will have an enumerable of pairs of types and delegate that we can use to populate our dictionary.
Note: the above code still needs some work (for example, could we just call GetParameters once?), and presumes a modern .NET target (extra work is needed to make it work in older platforms). Also notice the code for Type Discovery I present does not handle generic methods, you can check Type.IsGenericTypeDefinition and MethodInfo.IsGenericMethodDefinition... however, I would suggest to avoid them. In fact, it should be easy to modify for the case where you want to put all the methods in a single static class. You may also use a similar approach to get factory methods, for example.
If you have overloads, and you don't want to use a switch, you could use dynamic, however you really need to ask yourself if this is a design problem, and should be solved in a more appropriate way. I.e why do you need to store unrelated types in a list anyway?
public static void Test(Version version)
{
Console.WriteLine("is a version");
}
public static void Test(FormatException formatException)
{
Console.WriteLine("is a formatException");
}
static void Main(string[] args)
{
var list = new List<object>();
list.Add(new Version());
list.Add(new FormatException());
foreach (var item in list)
Test((dynamic)item);
}
Output
is a version
is a formatException
Full Demo Here
Note : this will all break if it can't find an overload. ka-bang! So I don't recommend using it, unless you really need to.
You can actually use standard System properties and methods to achieve your goal.
The first thing to do is get the Type:
var type = System.Type.GetType(elements.Name, false, true);
The false parameter indicates that you do not want to throw an exception on error and the true parameter indicates that you want to ignore case.
Once you have a valid type, you can call System.Activator to create a new instance of the class:
if (type != null) {
var classInstance = System.ServiceActivator.CreateInstance(type);
// Use the instance here
}
Note that this overload of CreateInstance requires a parameterless, public constructor. However, there are other overloads that allow you to pass parameters and access non-public constructors.
You can use Type.GetType method to get the type of object instead of doing a string comparision. Here's the same code:
foreach (var element in ListOfObjects)
{
var type = Type.GetType(element.Name);
if (type == typeof(YOUR_OBJECT_TYPE))
{
// Do Something
}
}
Read more about GetType here
I am not sure if i understand your question clearly but,
maybe it can help you, I don't think you need to keep type in name field since you can get type just like this. And i also don't get why do you want to cast this type again to itself.
foreach (var element in ListOfObjects)
{
var _type = element.getType()
}
and you can just use switch case or if statements for making route.
Surely using dictionary mapping Type and Method is possible:
Dictionary<Type, Action<Object>> methodMap = new Dictionary<Type, Action<Object>>();
Preloading the dictionary:
static void Action1(Object obj)
{
//do necessary casting here or not
Console.WriteLine("i handle Type1");
}
static void Action2(Object obj)
{
Console.WriteLine("i handle Type2");
}
Dictionary<Type, Action<Object>> methodMap = new Dictionary<Type, Action<Object>>();
methodMap[typeof(Type1)] = Action1;
methodMap[typeof(Type2)] = Action2;
And use the dictionary:
List<Object> collector = new List<Object>();
collector.Add(new Type1());
collector.Add(new Type2());
methodMap[collector[0].GetType()](collector[0]);
methodMap[collector[1].GetType()](collector[1]);
The type-method map also works for those class who's ancient is different. it would be the key factor you choose this kind method rather overloading or virtual member function.
If I have an expression in the form of Expression<Func<Delegate>> is it possible to determine the derived type of the object used to pass in the delegate? Does the expression even contain this information, or is it exclusively representative of the delegate.
A code example should make things clearer.
using System;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
namespace Sandbox {
public interface IContract {
void Method();
}
public class Concrete : IContract {
public void Method() { }
}
public class Test {
private IContract contract = new Concrete();
private Concrete concrete = new Concrete();
public static string GetFullMethodName(Expression<Func<Action>> expression) {
var unaryExpression = (UnaryExpression)expression.Body;
var methodCallExpression = (MethodCallExpression)unaryExpression.Operand;
var methodInfoExpression = (ConstantExpression)methodCallExpression.Arguments.Last();
var methodInfo = (MemberInfo)methodInfoExpression.Value;
var type = methodInfo.DeclaringType;
var name = methodInfo.Name;
return String.Format("{0}.{1}", type, name);
}
public Test() {
var strConcrete = GetFullMethodName(() => concrete.Method); // Sandbox.Concrete.Method
var strContract = GetFullMethodName(() => contract.Method); // Sandbox.IContract.Method
}
}
}
Is it possible to make () => contract.Method produce
Sandbox.Concrete.Method
Instead of
Sandbox.IContract.Method
Can the expression be altered to support this, or would I be forced to pass an instance of the object as a separate parameter in order to determine it's type?
No, that isn't possible.
The expression tree is built based on compile-time information, and at compile-time, the method being invoked is the virtual IContract.Method. The fact that at runtime, the Concrete.Method is actually invoked is irrelevant - that's handled in the virtual dispatch mechanism and the compiler finished its job long before any of this is decided.
The best you can do is try to emulate virtual dispatch yourself. For example, you could try enumerating the interface implementation on the this instance at runtime, and if you do find a method that matches the interface, you'd return that. However, this is certainly tricky - you need to be able to perfectly emulate the actual virtual dispatch.
Another tricky point is that the way you're trying to get the value is already broken. For example, in my environment, the methodInfoExpression is not a ConstantExpression - it's a field on a closure type. Your "parsing" is very fragile.
That said, it's also kind of unnecessary and overcomplicated - you're trying to receive an expression that returns an action and "steal" the value of the action out of the expression. There's already a simple way of doing that - pass that argument directly. No need to hide it in an expression tree:
public static string GetFullMethodName(Action action)
{
return string.Format("{0}.{1}", action.Method.DeclaringType.Name, action.Method.Name);
}
var strConcrete = GetFullMethodName(concrete.Method).Dump(); // Sandbox.Concrete.Method
var strContract = GetFullMethodName(contract.Method).Dump(); // Sandbox.Concrete.Method
You don't need expressions for things that basic reflection already gives you :)
I almost understand why this particular problem arises (though I more than welcome a layman's explanation if you can find the time!), it I'm sure involves boxing/unboxing which I won't attempt to incorrectly explain..
With my current knowledge (or lack thereof), of the situation, I'm not sure how best to proceed to resolve it.
Here is a fairly simplified console app showing my issue:
static void Main(string[] args)
{
try
{
// succeeds
IEnumerable<Expression<Func<TestCase1Impl, dynamic>>> results1 =
typeof(ITestCase1).GetMethods().Select(m => buildDynamicExpression(new TestCase1Impl(), m));
Console.WriteLine("{0} methods processed on ITestCase1", results1.Count().ToString());
// succeeds
IEnumerable<Expression<Func<TestCase2Impl, int>>> results2 =
typeof(ITestCase2).GetMethods().Select(m => buildTypedExpression(new TestCase2Impl(), m));
Console.WriteLine("{0} methods processed on ITestCase2", results2.Count().ToString());
// fails
IEnumerable<Expression<Func<TestCase2Impl, dynamic>>> results3 =
typeof(ITestCase2).GetMethods().Select(m => buildDynamicExpression(new TestCase2Impl(), m));
Console.WriteLine("{0} methods processed on ITestCase2", results3.Count().ToString());
}
catch (Exception ex)
{
Console.WriteLine("Failed: {0}", ex.ToString());
}
Console.ReadKey();
}
private static Expression<Func<T, dynamic>> buildDynamicExpression<T>(T arg, MethodInfo method)
{
ParameterExpression param = Expression.Parameter(typeof(T));
MethodCallExpression[] args = new MethodCallExpression[0]; // none of the methods shown take arguments
return Expression.Lambda<Func<T, dynamic>>(Expression.Call(param, method, args), new ParameterExpression[] { param });
}
private static Expression<Func<T, int>> buildTypedExpression<T>(T arg, MethodInfo method)
{
ParameterExpression param = Expression.Parameter(typeof(T));
MethodCallExpression[] args = new MethodCallExpression[0]; // none of the methods shown take arguments
return Expression.Lambda<Func<T, int>>(Expression.Call(param, method, args), new ParameterExpression[] { param });
}
public interface ITestCase1
{
string Method1();
List<int> Method2();
Program Method3();
}
public interface ITestCase2
{
int Method4();
}
private class TestCase1Impl : ITestCase1
{
public string Method1()
{
throw new NotImplementedException();
}
public List<int> Method2()
{
throw new NotImplementedException();
}
public Program Method3()
{
throw new NotImplementedException();
}
}
private class TestCase2Impl : ITestCase2
{
public int Method4()
{
throw new NotImplementedException();
}
}
The above will output
3 methods processed on ITestCase1
1 methods processed on ITestCase2
Failed: System.ArgumentException: Expression of type 'System.Int32' cannot be used for return type 'System.Object' <irrelevant stack trace follows>
As is often the case with these issues, it's better to examine where it was you started before getting into this terrible mess.
I'm using Moq. I have a common interface used widely across my application by other interfaces. I have a need to test that my interface consumers first call a particular method on the common interface, before calling any methods on the various interfaces (this to me sounds like a bad design in hindsight, I may address that later but for purely academic reasons, I'd like to solve this issue first).
In order to this, I dynamically generate expressions for each method on my interfaces with It.IsAny<T>() arguments, which I can then pass to a mock.Setup(generatedExpression).Callback(doSomethingCommonHere).
It may well be that there is a easier way to do this instead of my expression building...?
If not however, my question is, what is the best way to amend my expression building to allow for value types?
This isn't specific to dynamic. You will get the same result if you replace dynamic with object. You would even get that for custom value types that implement an interface and you want to return them from a Func<IImplementedInterface>.
The reason for this is the fact that when you want to return an int as object it has to be boxed - as you correctly guessed.
The expression that is used for boxing is Expression.Convert. Adding that to your code will fix the exception:
private static Expression<Func<T, dynamic>> BuildDynamicExpression<T>(
T arg,
MethodInfo method)
{
ParameterExpression param = Expression.Parameter(typeof(T));
var methodCall = Expression.Call(param, method);
var conversion =
return Expression.Lambda<Func<T, dynamic>>(
Expression.Convert(methodCall, typeof(object)),
new ParameterExpression[] { param });
}
BTW: As you can see, I removed the args array. It is not necessary.
To work around the problem with Moq I think you need to change the approach a bit.
The idea is the following:
Create an expression with the exact return type of the called method.
Let the DLR (Dynamic Language Runtime) figure out the type of the expression.
In Code:
IEnumerable<Expression> results =
typeof(ITestCase2).GetMethods()
.Select(m => BuildDynamicExpression(
new TestCase2Impl(), m));
BuildDynamicExpression looks like this:
private static Expression BuildDynamicExpression<T>(T arg, MethodInfo method)
{
ParameterExpression param = Expression.Parameter(typeof(T));
return Expression.Lambda(Expression.Call(param, method),
new ParameterExpression[] { param });
}
Usage would be like this:
foreach(var expression in results)
{
mock.Setup((dynamic)expression);
// ...
}
The important part here is the cast to dynamic before passing the expression to Setup.