I was fiddling with compiled delegates and tried to call Serialize and Deserialize functions in the following class using compile delegates (don't mind the names). I had success in calling Serialize, but not Deserialize. The problem seem to be I don't seem to understand how to pass the string argument to the Func object in the following code. Does anyone know a fix to my code (and brain)?
public class SomeClass
{
public string SomeString { get; }
public SomeClass(string str)
{
SomeString = str;
}
public string Serialize()
{
return SomeString;
}
public SomeClass Deserialize(string str)
{
return new SomeClass(str + " - !!!!");
}
}
public class Program
{
private static class TypeSerializationCache<T>
{
public static readonly Func<T, string> Serialize;
public static readonly Func<string, T> DeserializeThatShouldBe;
public static readonly Func<T, string, T> DeserializeOriginalFixed;
static TypeSerializationCache()
{
const string SerializeFunctionToCall = "Serialize";
var serializeFuncParameterValue = Expression.Parameter(typeof(T), "serializeFuncParameterValue");
var serializeMethod = typeof(T).GetMethod(SerializeFunctionToCall, BindingFlags.Instance | BindingFlags.Public, null, new Type[] { }, null);
var serializeCall = serializeMethod != null ? (Expression)Expression.Call(serializeFuncParameterValue, serializeMethod) : Expression.Constant(default(T), typeof(T));
Serialize = Expression.Lambda<Func<T, string>>(serializeCall, serializeFuncParameterValue).Compile();
const string DeserializeCallFunction = "Deserialize";
var deserializeFuncParameterValue = Expression.Parameter(typeof(T), "DeserializeFuncParameterValue");
var deserializeMethod = typeof(T).GetMethod(DeserializeCallFunction, BindingFlags.Instance | BindingFlags.Public, null, new Type[] { typeof(string) }, null);
var deserializeArgument = Expression.Parameter(typeof(string), "deserializeArgument");
var deserializeCall = Expression.Call(deserializeFuncParameterValue, deserializeMethod, deserializeArgument);
DeserializeOriginalFixed = Expression.Lambda<Func<T, string, T>>(deserializeCall, deserializeFuncParameterValue, deserializeArgument).Compile();
//To my great dismay, the following throws.
DeserializeThatShouldBe = Expression.Lambda<Func<string, T>>(deserializeCall, deserializeFuncParameterValue, deserializeArgument).Compile();
}
}
public static void Main(string[] args)
{
var class11 = new SomeClass("XYZ");
var class12 = new SomeClass("123");
var class31 = TypeSerializationCache<SomeClass>.Serialize(class11);
var class32 = TypeSerializationCache<SomeClass>.Serialize(class12);
var class31d = TypeSerializationCache<SomeClass>.DeserializeOriginalFixed(class11, class31);
var class32d = TypeSerializationCache<SomeClass>.DeserializeThatShouldBe(class32);
}
<edit: I needed to come back (awake) and make this attempt to fix the number of parameters. Not quite what I was hoping for, ideally I'd like to use just the type parameter and the serialized string. Also, duck talk reminds me of bug talk. :)
Aanyway, I'm still in search of the root fix, not just band-aid...
<edit 2: Now, the root fix appears to be in my brain and to understand one needs an instance for an instance method, or a static method. I think I got my ducks lined up and counted for after a good shut-eyes. My thanks to Eric.
Does anyone know a fix to my code
Show a programmer where the bug is, they fix the bug. Teach the programmer how to find the bug, and they stop posting their buggy code for other people to debug for them, saving everyone time.
Obtain a rubber duck. Read this line out loud to the duck.
var deserializeFuncParameterValue = Expression.Parameter(typeof(T), "DeserializeFuncParameterValue");
Now read this line out loud to the duck.
Deserialize = Expression.Lambda<Func<string, T>>(deserializeCall, deserializeFuncParameterValue, deserializeArgument).Compile();
Now explain to the duck like the duck is completely ignorant of expression trees why it is that the code is correct. Since the code is not correct, you should be unable to do so. The specific point at which you are unable to do so is either the bug, or a point where there is correct code that you cannot justify. Either way, you've learned something about the code, and probably you've found the bug.
Hint: The error message is not wrong. If you need to, read the error message out loud to the duck as well.
(The original poster has neglected to post the error message, which is "Incorrect number of parameters supplied for lambda declaration".)
(and brain)?
Rubber duck debugging works because it does an end run around the part of your brain that is stopping you from finding the bug. Your brain wants to believe that the code you wrote is correct, and it is literally not allowing you to see the obvious problem. You read the code, your eyes glaze over a little bit, and it is "obviously correct". Well no, it is not.
Explaining it to the duck forces your brain to re-examine the incorrect assumptions that led you to believe that the wrong code was "obviously correct".
Note that it works for mechanical engineering problems and stuffed ducks too.
Related
I have a simple ApiController that I am trying to catch and return an error. This was for a quick OnExceptionAspect demo but I ran into a snag: I can't figure out how to return BadRequest as the args.ReturnValue. I thought it would be simpler than this. This is my first time using PostSharp in a very long time and certainly the first time while using ASP.Net Core.
Note: I have a bad connection string on the context to force a quick error (not shown).
ParentController
[HttpGet("Get/{studentId}")]
[ActionResultExceptionAspect(StatusCode = HttpStatusCode.BadRequest)]
public ActionResult<IEnumerable<ParentModel>> RetrieveParents(string studentId)
{
var query = Context.ParentViews
.Where(x => x.StudentID == studentId)
.Select(s => EntityMapper.MapFromEntity(s));
return query.ToArray();
}
ActionResultExceptionAspect
public override void OnException(MethodExecutionArgs args)
{
args.FlowBehavior = FlowBehavior.Return;
args.ReturnValue = ((StudentControllerBase)args.Instance).BadRequest();
}
I get an error of:
System.InvalidCastException: Unable to cast object of type 'Microsoft.AspNetCore.Mvc.BadRequestResult' to type 'Microsoft.AspNetCore.Mvc.ActionResult`1[System.Collections.Generic.IEnumerable`1[Student.Models.ParentModel]]'.
The problem seems to be an instance based issue. I see a lot of solutions that seem overly complicated for what I needed so I went with the simplest way to resolve this until I can find something better. I have seen this as an issue specific for ActionResult<T> return types whenever generated outside the instance. This seems simple with generics for purposes of unit tests but since this is runtime and hard to resolve an unknown return type I went with Activator.CreateInstance
My new OnException method is:
public override void OnException(MethodExecutionArgs args)
{
var methType = ((MethodInfo)args.Method).ReturnType;
args.ReturnValue = Activator.CreateInstance(methType, ((ControllerBase)args.Instance).BadRequest());
args.FlowBehavior = FlowBehavior.Return;
}
I am by no means sure this is the right way to do it, but it works for this instance.
I'm generating a random number from 1-1000. I have 200 functions named function1, function4, function 10, function 11, etc. What I would like to do is execute a specific function depending on if the number generated requires a function, and ignore it if not.
My first thought was to create an int[] containing all of the values that would trigger a function, and if the int[] contains the random number to use if statements to figure out what the number is. I'm concerned that it must be a really crude solution to an easy problem though.
I know the "best way" to do something is subjective, but is there a better way to accomplish this?
UPDATE: As per comments, I should probably have started out by pointing out that doing this for 200 functions is probably a good sign that there is some serious issue in your design. This is probably an XY question where you are trying to solve a problem in some crazy way and asking about your intended solution instead of asking about the problem itself.
That said I'll leave the original answer because it's still good advice when mapping a reasonable amount of function calls that can/will change during the life cylce of your app or dynamically as the code runs.
I won't get into why you are doing this, but I'll try to at least point you in the right direction so this doesn't become a complete nightmare when you need to modify/expand behavior:
You can map numbers to function calls using delegates and a dictionary. Assuming your functions take no arguments and return void you'd do:
var functionsMap = new Dictionary<int, Action>();
//map functions
var r = getSomeRandomNumber();
if (functions.TryGetValue(r), out var a)
a(); //invoke function
Mapping functions is simply adding keys and values:
functionsMap.Add(1, () => function1());
functionsMap.Add(3, () => function3());
//etc.
If your functions take arguments or return values, you'd use the adequate delegate: Action<T>, Func<T1, T2> etc.
You can use reflection to invoke appropriate method:
Type exampleType = exampleObject.GetType();
MethodInfo exampleMethod = exampleType.GetMethod(methodName);
exampleMethod.Invoke(this, null);
Where methodName can be created using your random number.
Without commenting on the wisdom of having 200 functions named the way yours are, you can use reflection to determine whether a given functionX() exists, like so:
public void ExecuteDynamicMethod(int number)
{
// Modify these two lines with your app's dll/exe and class type:
Assembly assembly = Assembly.LoadFile("...Assembly1.dll");
Type type = assembly.GetType("YourClassType");
if (type != null)
{
MethodInfo methodInfo = type.GetMethod("function" + number);
if (methodInfo != null)
{
object classInstance = Activator.CreateInstance(type, null);
methodInfo.Invoke(classInstance, null); // null = "no function arguments"
}
}
}
This can then be called for a given value like
ExecuteDynamicMethod(14);
See this SO answer for the inspiration behind this.
Reflection can be used for this purpose. I want to give and keep below example for not only the objective of the question but also for future reference. Also, of course that many function is not good but below code shows the approach that can work with many functions if they have similar name (like starting with "function" keyword).
Assume below is Methods.cs
using System;
using System.Reflection;
namespace YourMethodNamespace
{
public class YourMethodClass
{
public void function1()
{
Console.WriteLine("Function-1");
}
public void function2()
{
Console.WriteLine("Function-2");
}
...
public void function200()
{
Console.WriteLine("Function-200");
}
public static void invokeMethodsDynamically(int randomNumber){
Type yourClassType = typeof(YourMethodClass);
ConstructorInfo yourClassConstructorInfo = yourClassType.GetConstructor(Type.EmptyTypes);
object yourClassObject = yourClassConstructorInfo.Invoke(new object[]{});
//If the constructor has parameters, then we can pass them by this way. Like below;
/*ConstructorInfo yourClassConstructorInfo = yourClassType.GetConstructor(new[]{typeof(int)});
object yourClassObject = yourClassConstructorInfo.Invoke(new object[]{3});
*/
MethodInfo[] methodInfoArr = yourClassType.GetMethods();
foreach(MethodInfo methodInfo in methodInfoArr){
if(methodInfo.Name == "function" + randomNumber){
methodInfo.Invoke(yourClassObject, null);
}
}
}
}
}
Let's say below is Program.cs
using System;
using YourMethodNamespace;
namespace YourProgramNamespace
{
public class YourProgramClass
{
public static void Main()
{
Random random = new Random();
int randomNumber = random.Next(1, 201);
//If Methods.cs is in another Assembly
/*string pathToDllAssembly = #"Domain.dll";
Assembly dllAssembly = Assembly.LoadFrom(pathToDllAssembly);
Type methodsClassType = dllAssembly.GetType("YourMethodNamespace.YourMethodClass");
ConstructorInfo methodClassConstructorInfo = methodsClassType.GetConstructor(Type.EmptyTypes);
object methodsClassObject = methodClassConstructorInfo.Invoke(new object[]{});
MethodInfo methodInfo = methodsClassType.GetMethod("invokeMethodsDynamically");
methodInfo.Invoke(methodsClassObject, new object[]{randomNumber});
*/
YourMethodClass.invokeMethodsDynamically(randomNumber, null);
}
}
}
Also for testing and observing, below link can be used.
https://repl.it/#erdsavasci/ReflectionTest
I'm building up tooling for a piece of software and would like to be able save out the boolean expression in the source code that exists in a Debug.Assert (or Trace.Assert) call.
For example, if the program crashes with:
var x = -1;
Debug.Assert(x >= 0, "X must be non-negative", "some detail message");
I'd like to be able to get out the string "x >= 0" as well as the message and detail message.
I've looked into using a TraceListener, but TraceListener#Fail(string) and TraceListener#Fail(string, string) only can capture the message and detail message fields (which, in the case a developer does not include, leaves me with no easy way to report what went wrong).
I suppose it's possible to create a stack trace and read the particular line that failed and report that (assuming the source code is available), but this seems relatively fragile.
Thanks for your time!
You can use expressions to accomplish something rough:
public static class DebugEx
{
[Conditional("DEBUG")]
public static void Assert(Expression<Func<bool>> assertion, string message)
{
Debug.Assert(assertion.Compile()(), message, assertion.Body.ToString());
}
}
and use it like so:
var i = -1;
DebugEx.Assert(() => i > 0, "Message");
There are some down sides to this. The first is, you have to use a lambda, so that complicates the syntax a little bit. The second is since we are dynamically compiling things, there is a performance hit. Since this will only happen in Debug mode (hence the conditional), the performance loss won't be seen in Release mode.
Lastly, the output isn't pretty. It'll look something like this:
(value(WindowsFormsApplication1.Form1+<>c__DisplayClass0).i > 0)
There isn't a whole lot you can do about this. The reason this happens is because of the closure around i. This is actually accurate since that is what it gets compiled down into.
I had already started typing an answer when #vcsjones posted his answer, so I abandoned mine, but I see there are some parts of it that are still relevant. Primarily with regards to formatting the lambda expression into something readable, So I will merge his with that part of my intended answer.
It uses a number of regular expressions to format the assertion expression, so that in many cases it will look decent (i.e. close to what you typed).
For the example given in #vcsjones answer it will now look like this:
Assertion '(i > 0)' failed.
public static class DebugEx
{
private static readonly Dictionary<Regex, string> _replacements;
static DebugEx()
{
_replacements = new Dictionary<Regex,string>()
{
{new Regex("value\\([^)]*\\)\\."), string.Empty},
{new Regex("\\(\\)\\."), string.Empty},
{new Regex("\\(\\)\\ =>"), string.Empty},
{new Regex("Not"), "!"}
};
}
[Conditional("DEBUG")]
public static void Assert(Expression<Func<bool>> assertion, string message)
{
if (!assertion.Compile()())
Debug.Assert(false, message, FormatFailure(assertion));
}
private static string FormatFailure(Expression assertion)
{
return string.Format("Assertion '{0}' failed.", Normalize(assertion.ToString()));
}
private static string Normalize(string expression)
{
string result = expression;
foreach (var pattern in _replacements)
{
result = pattern.Key.Replace(result, pattern.Value);
}
return result.Trim();
}
}
First of all, sorry if this has been asked before. I've done a pretty comprehensive search and found nothing quite like it, but I may have missed something.
And now to the question: I'm trying to invoke a constructor through reflection, with no luck. Basically, I have an object that I want to clone, so I look up the copy constructor for its type and then want to invoke it. Here's what I have:
public Object clone(Object toClone) {
MethodBase copyConstructor = type.GetConstructor(
new Type[] { toClone.GetType() });
return method.Invoke(toClone, new object[] { toClone }); //<-- doesn't work
}
I call the above method like so:
List<int> list = new List<int>(new int[] { 0, 1, 2 });
List<int> clone = (List<int>) clone(list);
Now, notice the invoke method I'm using is MethodBase's invoke. ConstructorInfo provides an invoke method that does work if invoked like this:
return ((ConstructorInfo) method).Invoke(new object[] { toClone });
However, I want to use MethodBase's method, because in reality instead of looking up the copy constructor every time I will store it in a dictionary, and the dictionary contains both methods and constructors, so it's a Dictionary<MethodBase>, not Dictionary<ConstructorInfo>.
I could of course cast to ConstructorInfo as I do above, but I'd rather avoid the casting and use the MethodBase method directly. I just can't figure out the right parameters.
Any help? Thanks so much.
EDIT
Benjamin,
Thanks so much for your suggestions. I was actually doing exactly what you suggest in your second edit, except (and that's a big "except") my dictionary was where
class ClonerMethod {
public MethodBase method;
public bool isConstructor;
...
public Object invoke(Object toClone) {
return isConstructor ?
((ConstructorInfo) method).Invoke(new object[] { toClone }) : //<-- I wanted to avoid this cast
method.Invoke(toClone, null);
}
}
And then I called ClonerMethod's invoke on what I found in the dictionary. I didn't add the code the deals with all that because the answer I was looking for was just how to call Invoke on a ConstructorInfo using MethodBase's Invoke method, so I didn't want to add unnecessary info and too much code for you guys to read through. However, I like your use of Func<,> much MUCH better, so I'm switching to that. Also making the Clone method generic is a nice addition, but in my case the caller doesn't know the type of the object, so I'll keep it non-generic instead.
I didn't know about Func<,>, and if I knew about the lambda operator I had forgotten (I hadn't really needed something like this before), so I've actually learnt a lot from your answer. I always love to learn new things, and this will come in very handy in the future, so thanks a lot! :)
If you know that the object is having a constructor like that, did you think about using this overload of Activator.CreateInstance instead?
Update: So you have a cascading search for MethodInfo/MethodBase already and store them -> You don't want/cannot use Activator.
In that case I don't see a way to do what you want without a cast. But - maybe you could change the architecture to store a Dictionary<Type, Func<object, object>> and add those Func<> instances instead. Makes the calling code nicer (I assume) and would allow you to do this cast once:
// Constructor
dictionary.Add(type,
source => ((ConstructorInfo) method).Invoke(new object[] {source})
);
// Clone
dictionary.Add(type,
source => method.Invoke(source, new object[]{})
);
In fact, since you only care about the difference between constructor and normal method at the very site where you grab them, you wouldn't need a cast at all, would you?
// Constructor 2
dictionary.Add(type,
source => yourConstructorInfo.Invoke(new object[] {source})
);
Unless I'm missing something (quite possible, of course) this could resolve the problem by doing this once on the defining side of the fence and the caller wouldn't need to mind if this is constructor or not?
One last time, then I'm going to stop the edit spam. I was bored and came up with the following code. Is that what you are trying to accomplish?
public class Cloner {
private readonly IDictionary<Type, Func<object, object>> _cloneMap =
new Dictionary<Type, Func<object, object>>();
public T Clone<T>(T source) {
Type sourceType = source.GetType();
Func<object, object> cloneFunc;
if (_cloneMap.TryGetValue(sourceType, out cloneFunc)) {
return (T)cloneFunc(source);
}
if (TryGetCopyConstructorCloneFunc(sourceType, out cloneFunc)) {
_cloneMap.Add(sourceType, cloneFunc);
return (T)cloneFunc(source);
}
if (TryGetICloneableCloneFunc(sourceType, out cloneFunc)) {
_cloneMap.Add(sourceType, cloneFunc);
return (T)cloneFunc(source);
}
return default(T);
}
private bool TryGetCopyConstructorCloneFunc(Type type,
out Func<object, object> cloneFunc) {
var constructor = type.GetConstructor(new[] { type });
if (constructor == null) {
cloneFunc = source => null;
return false;
}
cloneFunc = source => constructor.Invoke(new[] { source });
return true;
}
private bool TryGetICloneableCloneFunc(Type type,
out Func<object, object> cloneFunc) {
bool isICloneable = typeof(ICloneable).IsAssignableFrom(type);
var cloneMethod = type.GetMethod("Clone", new Type[] { });
if (!isICloneable || (cloneMethod == null)) {
cloneFunc = source => null;
return false;
}
cloneFunc = source => cloneMethod.Invoke(source, new object[] {});
return true;
}
}
Going from a lambda to an Expression is easy using a method call...
public void GimmeExpression(Expression<Func<T>> expression)
{
((MemberExpression)expression.Body).Member.Name; // "DoStuff"
}
public void SomewhereElse()
{
GimmeExpression(() => thing.DoStuff());
}
But I would like to turn the Func in to an expression, only in rare cases...
public void ContainTheDanger(Func<T> dangerousCall)
{
try
{
dangerousCall();
}
catch (Exception e)
{
// This next line does not work...
Expression<Func<T>> DangerousExpression = dangerousCall;
var nameOfDanger =
((MemberExpression)dangerousCall.Body).Member.Name;
throw new DangerContainer(
"Danger manifested while " + nameOfDanger, e);
}
}
public void SomewhereElse()
{
ContainTheDanger(() => thing.CrossTheStreams());
}
The line that does not work gives me the compile-time error Cannot implicitly convert type 'System.Func<T>' to 'System.Linq.Expressions.Expression<System.Func<T>>'. An explicit cast does not resolve the situation. Is there a facility to do this that I am overlooking?
Ooh, it's not easy at all. Func<T> represents a generic delegate and not an expression. If there's any way you could do so (due to optimizations and other things done by the compiler, some data might be thrown away, so it might be impossible to get the original expression back), it'd be disassembling the IL on the fly and inferring the expression (which is by no means easy). Treating lambda expressions as data (Expression<Func<T>>) is a magic done by the compiler (basically the compiler builds an expression tree in code instead of compiling it to IL).
Related fact
This is why languages that push lambdas to the extreme (like Lisp) are often easier to implement as interpreters. In those languages, code and data are essentially the same thing (even at run time), but our chip cannot understand that form of code, so we have to emulate such a machine by building an interpreter on top of it that understands it (the choice made by Lisp like languages) or sacrificing the power (code will no longer be exactly equal to data) to some extent (the choice made by C#). In C#, the compiler gives the illusion of treating code as data by allowing lambdas to be interpreted as code (Func<T>) and data (Expression<Func<T>>) at compile time.
private static Expression<Func<T, bool>> FuncToExpression<T>(Func<T, bool> f)
{
return x => f(x);
}
What you probably should do, is turn the method around. Take in an Expression>, and compile and run. If it fails, you already have the Expression to look into.
public void ContainTheDanger(Expression<Func<T>> dangerousCall)
{
try
{
dangerousCall().Compile().Invoke();;
}
catch (Exception e)
{
// This next line does not work...
var nameOfDanger =
((MemberExpression)dangerousCall.Body).Member.Name;
throw new DangerContainer(
"Danger manifested while " + nameOfDanger, e);
}
}
public void SomewhereElse()
{
ContainTheDanger(() => thing.CrossTheStreams());
}
Obviously you need to consider the performance implications of this, and determine if it is something that you really need to do.
If you sometimes need an expression and sometimes need a delegate, you have 2 options:
have different methods (1 for each)
always accept the Expression<...> version, and just .Compile().Invoke(...) it if you want a delegate. Obviously this has cost.
NJection.LambdaConverter is a library that converts a delegate to an expression
public class Program
{
private static void Main(string[] args) {
var lambda = Lambda.TransformMethodTo<Func<string, int>>()
.From(() => Parse)
.ToLambda();
}
public static int Parse(string value) {
return int.Parse(value)
}
}
You can go the other way via the .Compile() method however - not sure if this is useful for you:
public void ContainTheDanger<T>(Expression<Func<T>> dangerousCall)
{
try
{
var expr = dangerousCall.Compile();
expr.Invoke();
}
catch (Exception e)
{
Expression<Func<T>> DangerousExpression = dangerousCall;
var nameOfDanger = ((MethodCallExpression)dangerousCall.Body).Method.Name;
throw new DangerContainer("Danger manifested while " + nameOfDanger, e);
}
}
public void SomewhereElse()
{
var thing = new Thing();
ContainTheDanger(() => thing.CrossTheStreams());
}
Expression<Func<T>> ToExpression<T>(Func<T> call)
{
MethodCallExpression methodCall = call.Target == null
? Expression.Call(call.Method)
: Expression.Call(Expression.Constant(call.Target), call.Method);
return Expression.Lambda<Func<T>>(methodCall);
}
JB Evain from the Cecil Mono team is doing some progress to enable this
http://evain.net/blog/articles/2009/04/22/converting-delegates-to-expression-trees
Change
// This next line does not work...
Expression<Func<T>> DangerousExpression = dangerousCall;
To
// This next line works!
Expression<Func<T>> DangerousExpression = () => dangerousCall();