How to get debuginfo to work on compiled delegate - c#

I am working on a pet project: A programing language in the Javascript/Scheme mindset the project can be found here
I have looked through existing Stackoverflow questions such as Making a CLR/.NET Language Debuggable. However most of these solutions deal with generating assemblies. For numerous reasons I would prefer to avoid creating a new assembly.
class Program
{
public static void ThrowingFunction()
{
throw new Exception("Test Exception");
}
static void Main(string[] args)
{
Action thw = ThrowingFunction;
ParameterExpression param = Expression.Parameter(typeof(int), "arg");
SymbolDocumentInfo info = Expression.SymbolDocument("example-script", new Guid("83c65910-8376-11e2-9e96-0800200c9a66"));
Expression<Func<int,int>> exp = Expression.Lambda<Func<int,int>>(
Expression.Block(
Expression.DebugInfo(info,1,1,1,20),
Expression.Invoke(Expression.Constant(thw, typeof(Action))),
Expression.Add(param,Expression.Constant(1))
),
new List<ParameterExpression> { param }
);
Console.WriteLine(exp);
Func<int,int> Fn = exp.Compile(DebugInfoGenerator.CreatePdbGenerator());
try {
Fn(1);
}
catch (Exception e) {
Console.WriteLine(e);
Console.WriteLine(e.InnerException);
}
}
}
The above code works however the debug info does not contain the line information for the lambda instead referring obliquely to lambda_method with no other information in the stack trace.
How can I get the stack trace to also show line information.

Related

Get name from variable in calling method - creating calling method signature, parameters and values

I'm looking for a way to get hold of the name of a variable that was passed into an extensionmethod. I want to have the name of the parameter in the calling variable. Sounds strange, let me explain.
assume this piece of testing code
private static void TestingMethod(string firstParam, int secondParam, bool thirdParam)
{
try
{
throw new InvalidOperationException("This named optional params stuff, it's just not working boss");
}
catch (Exception ex)
{
GenericLog_Exception(ex, "it's on fire, please help");
}
}
On the last line you can see the exception being logged. I want to be able to provide optional parameter support. So the developers can add parameter information when needed.
I've seen many posts about this on stackoverflow, lot's of different approaches. Main thing is; it can't be done fully generically.
Some code for explanation:
static string GetCallingMethodSignature()
{
StackTrace stackTrace = new StackTrace();
// Get calling method name
var callingMethod = stackTrace.GetFrame(1).GetMethod();
var callingMethod_Name = callingMethod.Name;
// get calling method params
string retVal = string.Empty;
var callingMethod_Parameters = callingMethod.GetParameters();
retVal = callingMethod_Name + "(";
foreach (var param in callingMethod_Parameters)
{
retVal += param.Name + ": " + param.ToString() + ",";
}
retVal.Remove(retVal.Length - 1, 1);
retVal += ")";
return retVal;
}
Now, this testing code is getting the calling method name and it's parameters. That is, the names of the parameters. But not their values. The param.tostring() part only returns the type name. Not the value. I've been reading on this and it seems this can't be done via reflection.
So then I went for another approach, why not provide the parameters the developer finds suitable for logging. You don't need all of them most of the time anyway.
private static string GenericLog_Exception(Exception exceptionData, string extraInformation, params KeyValuePair<string, object>[] parameters)
So, this being a new testmethod, i'm providing the parameters of choice into the exception logging method. But if you want to make this work, it's one hell of a job everytime to make this call.
private static void TestingMethod(string firstParam, int secondParam, bool thirdParam)
{
try
{
throw new InvalidOperationException("This named optional params stuff, it's just not working boss");
}
catch (Exception ex)
{
GenericLog_Exception(ex, "it's on fire, please help", new KeyValuePair<string, object>[]{
new KeyValuePair<string, object>("firstParam", firstParam),
new KeyValuePair<string, object>("secondParam", secondParam),
new KeyValuePair<string, object>("thirdParam", thirdParam)
});
}
}
Now this is working. But as said, i find the bottom part to cumbersome. I was thinking along the lines of an extensionmethod, so I can shorten the creation of each kvp.
internal static class ExtensionMethodsForTesting
{
internal static KeyValuePair<string, object> AsKeyValuePair(this string parameter)
{
var name = nameof(parameter);
return new KeyValuePair<string, object>(name, parameter);
}
}
And this would then be used as
GenericLog_Exception(ex, "it's on fire, please help", new KeyValuePair<string, object>[] { firstParam.AsKeyValuePair() });
This confronts me with the same issue I had before; the nameof(parameter), ofcourse, returns "parameter". I would also have to make a couple of extension methods for each type. Or check for the type in the extension method to make sure i get the correct value.
So, in short: how can i get the name of this variable that invokes the extension method?
You could do the following "hack". Change the signature of your method to the following:
private static string GenericLog_Exception(
Exception exceptionData,
string extraInformation,
params Expression<Func<object>>[] parameters)
And now your call site would look a little bit cleaner:
GenericLog_Exception(ex,
"it's on fire, please help",
() => firstParam,
() => secondParam,
() => thirdParam);
And you can extract parameter info from the expressions the following way (using C# tuple support for convenience):
private static (object Value, string ParamName) GetParameterInfo
(Expression<Func<object>> expr)
{
//First try to get a member expression directly.
//If it fails we know there is a type conversion: parameter is not an object
//(or we have an invalid lambda that will make us crash)
//Get the "to object" conversion unary expression operand and then
//get the member expression of that and we're set.
var m = (expr.Body as MemberExpression) ??
(expr.Body as UnaryExpression).Operand as MemberExpression;
return (expr.Compile().Invoke(), m.Member.Name);
}

Getting unexpected crash reports inside a try-catch block

I'm using HockeyApp to collect crash data for my app, but for some reason it doesn't provide the stack trace.
What I have is something like that:
MyNamespace!<BaseAddress>+0x5d1287
MyNamespace!<BaseAddress>+0x5f18d5
MyNamespace!<BaseAddress>+0x5f1827
Microsoft.HockeyApp.Extensibility.Windows.UnhandledExceptionTelemetryModule.CoreApplication_UnhandledErrorDetected(Object sender, ApplicationModel.Core.UnhandledErrorDetectedEventArgs e)
so it's kinda hard to find out what's happening.
The exception message is helpful tho, as it says
Element not found. Cannot find credential in Vault
and there's just one place in which I'm using PasswordVault.
The problem here is that I'm using it inside a try/catch block, so I really don't understand why I'm getting this report, and I can't even reproduce it.
This is the full PasswordVaultService class, so that you can see exactly what I'm doing.
public class PasswordVaultService
{
private static readonly PasswordVault Vault = new PasswordVault();
public static string RetrieveSecret(Entry entry)
{
try
{
var results = Vault.FindAllByResource(entry.Name);
if (results.Count == 0) return null;
var result = results[0];
result.RetrievePassword();
return result.Password;
}
catch (Exception)
{
return null;
}
}
public static void StoreSecret(Entry entry, string secret)
{
Vault.Add(new PasswordCredential(entry.Name, entry.Name, secret));
}
public static void DeleteSecret(Entry entry)
{
var results = Vault.FindAllByResource(entry.Name);
if (results.Count == 0) return;
var result = results[0];
Vault.Remove(result);
}
}
I've been getting this error for some time now, and I don't understand what's going on because the class is quite simple. Before posting I've even searched for Vault inside the project and this is the only place where I'm using the PasswordVault.

Backendless API - Create user

I'm trying to use Backendless API on a C# .net 4.5 application, but there is no way to make it work, since I get
"An unhandled exception of type 'System.StackOverflowException'
occurred in weborb.dll."
Code is simple, but doesn't work. The Java sample with Java BE Api worked normally.
public static void init()
{
Backendless.InitApp(APP_ID, SECRET_KEY, VERSION);
}
public static void RegisterUser()
{
BackendlessUser user = new BackendlessUser();
string error;
user.SetProperty("ID", "id");
user.SetProperty("password","12");
try
{
Backendless.UserService.Register(user); //StackOverflow error here
}
catch (BackendlessException exception)
{
error = exception.FaultCode;
}
}
From the linked sample:
static void Main( string[] args )
{
Backendless.InitApp( APP_ID, SECRET_KEY, VERSION_ID );
BackendlessUser loggedInUser = Backendless.UserService.Login( USER_NAME, PASS_WORD );
System.Console.WriteLine( "logged in user - " + loggedInUser.Email );
}
Backendless team solved this for me, link to the sample in the comments.

CppCodeProvider, CompileAssemblyFromFile throws System.NotImplementedException

The documentation for compiling C++/CLI using the frameworks CodeDom classes is somewhat lacking.
The background: I'm trying to write system tests for a piece of software I have written. The software generates code, and I want to test that the code can be compiled, and that the compiled code works as intended.
The code to be compiled and tested resides in a couple of source files. I want to compile the source file into an assembly, and then dynamically invoke the methods in it. I have experimented with doing the same C# sources, and I had a successful build and test in minutes. The C++ compiler always throws System.NotImplementedException.
Here's the code that blows up on me:
namespace CppCompilerTest {
class Program {
static void Main(string[] args) {
try {
string strSourceDir = #"D:\Projects\CppCompilerTest\CppSource";
using (var codeProvider = new CppCodeProvider7()) {
var options = new CompilerParameters { GenerateExecutable = false, GenerateInMemory = false };
options.ReferencedAssemblies.Add("System.dll");
CompilerResults results = codeProvider.CompileAssemblyFromFile(
options,
new[] {
Path.Combine(strSourceDir, "SourceFile1.cpp"),
Path.Combine(strSourceDir, "SourceFile2.cpp")
}
);
}
} catch(Exception ex) {
Console.WriteLine(ex);
}
Console.WriteLine("Press any key to continue");
Console.ReadKey();
}
}
}
Have I totally overlooked something? I'm wondering if maybe the cl.exe way is the faster route...

converting a .net Func<T> to a .net Expression<Func<T>>

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();

Categories