Get name of passed argument in C# method [duplicate] - c#

Let me use the following example to explain my question:
public string ExampleFunction(string Variable) {
return something;
}
string WhatIsMyName = "Hello World";
string Hello = ExampleFunction(WhatIsMyName);
When I pass the variable WhatIsMyName to the ExampleFunction, I want to be able to get a string of the original variable's name. Perhaps something like:
Variable.OriginalName.ToString() // == "WhatIsMyName"
Is there any way to do this?

What you want isn't possible directly but you can use Expressions in C# 3.0:
public void ExampleFunction(Expression<Func<string, string>> f) {
Console.WriteLine((f.Body as MemberExpression).Member.Name);
}
ExampleFunction(x => WhatIsMyName);
Note that this relies on unspecified behaviour and while it does work in Microsoft’s current C# and VB compilers, and in Mono’s C# compiler, there’s no guarantee that this won’t stop working in future versions.

This isn't exactly possible, the way you would want. C# 6.0 they Introduce the nameof Operator which should help improve and simplify the code. The name of operator resolves the name of the variable passed into it.
Usage for your case would look like this:
public string ExampleFunction(string variableName) {
//Construct your log statement using c# 6.0 string interpolation
return $"Error occurred in {variableName}";
}
string WhatIsMyName = "Hello World";
string Hello = ExampleFunction(nameof(WhatIsMyName));
A major benefit is that it is done at compile time,
The nameof expression is a constant. In all cases, nameof(...) is evaluated at compile-time to produce a string. Its argument is not evaluated at runtime, and is considered unreachable code (however it does not emit an "unreachable code" warning).
More information can be found here
Older Version Of C 3.0 and above
To Build on Nawfals answer
GetParameterName2(new { variable });
//Hack to assure compiler warning is generated specifying this method calling conventions
[Obsolete("Note you must use a single parametered AnonymousType When Calling this method")]
public static string GetParameterName<T>(T item) where T : class
{
if (item == null)
return string.Empty;
return typeof(T).GetProperties()[0].Name;
}

I know this post is really old, but since there is now a way in C#10 compiler, I thought I would share so others know.
You can now use CallerArgumentExpressionAttribute as shown
// Will throw argument exception if string IsNullOrEmpty returns true
public static void ValidateNotNullorEmpty(
this string str,
[CallerArgumentExpression("str")]string strName = null
)
{
if (string.IsNullOrEmpty(str))
{
throw new ArgumentException($"'{strName}' cannot be null or empty.", strName);
}
}
Now call with:
param.ValidateNotNullorEmpty();
will throw error: "param cannot be null or empty."
instead of "str cannot be null or empty"

static void Main(string[] args)
{
Console.WriteLine("Name is '{0}'", GetName(new {args}));
Console.ReadLine();
}
static string GetName<T>(T item) where T : class
{
var properties = typeof(T).GetProperties();
Enforce.That(properties.Length == 1);
return properties[0].Name;
}
More details are in this blog post.

Three ways:
1) Something without reflection at all:
GetParameterName1(new { variable });
public static string GetParameterName1<T>(T item) where T : class
{
if (item == null)
return string.Empty;
return item.ToString().TrimStart('{').TrimEnd('}').Split('=')[0].Trim();
}
2) Uses reflection, but this is way faster than other two.
GetParameterName2(new { variable });
public static string GetParameterName2<T>(T item) where T : class
{
if (item == null)
return string.Empty;
return typeof(T).GetProperties()[0].Name;
}
3) The slowest of all, don't use.
GetParameterName3(() => variable);
public static string GetParameterName3<T>(Expression<Func<T>> expr)
{
if (expr == null)
return string.Empty;
return ((MemberExpression)expr.Body).Member.Name;
}
To get a combo parameter name and value, you can extend these methods. Of course its easy to get value if you pass the parameter separately as another argument, but that's inelegant. Instead:
1)
public static string GetParameterInfo1<T>(T item) where T : class
{
if (item == null)
return string.Empty;
var param = item.ToString().TrimStart('{').TrimEnd('}').Split('=');
return "Parameter: '" + param[0].Trim() +
"' = " + param[1].Trim();
}
2)
public static string GetParameterInfo2<T>(T item) where T : class
{
if (item == null)
return string.Empty;
var param = typeof(T).GetProperties()[0];
return "Parameter: '" + param.Name +
"' = " + param.GetValue(item, null);
}
3)
public static string GetParameterInfo3<T>(Expression<Func<T>> expr)
{
if (expr == null)
return string.Empty;
var param = (MemberExpression)expr.Body;
return "Parameter: '" + param.Member.Name +
"' = " + ((FieldInfo)param.Member).GetValue(((ConstantExpression)param.Expression).Value);
}
1 and 2 are of comparable speed now, 3 is again sluggish.

Yes! It is possible. I have been looking for a solution to this for a long time and have finally come up with a hack that solves it (it's a bit nasty). I would not recommend using this as part of your program and I only think it works in debug mode. For me this doesn't matter as I only use it as a debugging tool in my console class so I can do:
int testVar = 1;
bool testBoolVar = True;
myConsole.Writeline(testVar);
myConsole.Writeline(testBoolVar);
the output to the console would be:
testVar: 1
testBoolVar: True
Here is the function I use to do that (not including the wrapping code for my console class.
public Dictionary<string, string> nameOfAlreadyAcessed = new Dictionary<string, string>();
public string nameOf(object obj, int level = 1)
{
StackFrame stackFrame = new StackTrace(true).GetFrame(level);
string fileName = stackFrame.GetFileName();
int lineNumber = stackFrame.GetFileLineNumber();
string uniqueId = fileName + lineNumber;
if (nameOfAlreadyAcessed.ContainsKey(uniqueId))
return nameOfAlreadyAcessed[uniqueId];
else
{
System.IO.StreamReader file = new System.IO.StreamReader(fileName);
for (int i = 0; i < lineNumber - 1; i++)
file.ReadLine();
string varName = file.ReadLine().Split(new char[] { '(', ')' })[1];
nameOfAlreadyAcessed.Add(uniqueId, varName);
return varName;
}
}

Continuing with the Caller* attribute series (i.e CallerMemberName, CallerFilePath and CallerLineNumber), CallerArgumentExpressionAttribute is available since C# Next (more info here).
The following example is inspired by Paul Mcilreavy's The CallerArgumentExpression Attribute in C# 8.0:
public static void ThrowIfNullOrWhitespace(this string self,
[CallerArgumentExpression("self")] string paramName = default)
{
if (self is null)
{
throw new ArgumentNullException(paramName);
}
if (string.IsNullOrWhiteSpace(self))
{
throw new ArgumentOutOfRangeException(paramName, self, "Value cannot be whitespace");
}
}

This would be very useful to do in order to create good exception messages causing people to be able to pinpoint errors better. Line numbers help, but you might not get them in prod, and when you do get them, if there are big statements in code, you typically only get the first line of the whole statement.
For instance, if you call .Value on a nullable that isn't set, you'll get an exception with a failure message, but as this functionality is lacking, you won't see what property was null. If you do this twice in one statement, for instance to set parameters to some method, you won't be able to see what nullable was not set.
Creating code like Verify.NotNull(myvar, nameof(myvar)) is the best workaround I've found so far, but would be great to get rid of the need to add the extra parameter.

No, but whenever you find yourself doing extremely complex things like this, you might want to re-think your solution. Remember that code should be easier to read than it was to write.

System.Environment.StackTrace will give you a string that includes the current call stack. You could parse that to get the information, which includes the variable names for each call.

Well Try this Utility class,
public static class Utility
{
public static Tuple<string, TSource> GetNameAndValue<TSource>(Expression<Func<TSource>> sourceExpression)
{
Tuple<String, TSource> result = null;
Type type = typeof (TSource);
Func<MemberExpression, Tuple<String, TSource>> process = delegate(MemberExpression memberExpression)
{
ConstantExpression constantExpression = (ConstantExpression)memberExpression.Expression;
var name = memberExpression.Member.Name;
var value = ((FieldInfo)memberExpression.Member).GetValue(constantExpression.Value);
return new Tuple<string, TSource>(name, (TSource) value);
};
Expression exception = sourceExpression.Body;
if (exception is MemberExpression)
{
result = process((MemberExpression)sourceExpression.Body);
}
else if (exception is UnaryExpression)
{
UnaryExpression unaryExpression = (UnaryExpression)sourceExpression.Body;
result = process((MemberExpression)unaryExpression.Operand);
}
else
{
throw new Exception("Expression type unknown.");
}
return result;
}
}
And User It Like
/*ToDo : Test Result*/
static void Main(string[] args)
{
/*Test : primivit types*/
long maxNumber = 123123;
Tuple<string, long> longVariable = Utility.GetNameAndValue(() => maxNumber);
string longVariableName = longVariable.Item1;
long longVariableValue = longVariable.Item2;
/*Test : user define types*/
Person aPerson = new Person() { Id = "123", Name = "Roy" };
Tuple<string, Person> personVariable = Utility.GetNameAndValue(() => aPerson);
string personVariableName = personVariable.Item1;
Person personVariableValue = personVariable.Item2;
/*Test : anonymous types*/
var ann = new { Id = "123", Name = "Roy" };
var annVariable = Utility.GetNameAndValue(() => ann);
string annVariableName = annVariable.Item1;
var annVariableValue = annVariable.Item2;
/*Test : Enum tyoes*/
Active isActive = Active.Yes;
Tuple<string, Active> isActiveVariable = Utility.GetNameAndValue(() => isActive);
string isActiveVariableName = isActiveVariable.Item1;
Active isActiveVariableValue = isActiveVariable.Item2;
}

Do this
var myVariable = 123;
myVariable.Named(() => myVariable);
var name = myVariable.Name();
// use name how you like
or naming in code by hand
var myVariable = 123.Named("my variable");
var name = myVariable.Name();
using this class
public static class ObjectInstanceExtensions
{
private static Dictionary<object, string> namedInstances = new Dictionary<object, string>();
public static void Named<T>(this T instance, Expression<Func<T>> expressionContainingOnlyYourInstance)
{
var name = ((MemberExpression)expressionContainingOnlyYourInstance.Body).Member.Name;
instance.Named(name);
}
public static T Named<T>(this T instance, string named)
{
if (namedInstances.ContainsKey(instance)) namedInstances[instance] = named;
else namedInstances.Add(instance, named);
return instance;
}
public static string Name<T>(this T instance)
{
if (namedInstances.ContainsKey(instance)) return namedInstances[instance];
throw new NotImplementedException("object has not been named");
}
}
Code tested and most elegant I can come up with.

Thanks for all the responses. I guess I'll just have to go with what I'm doing now.
For those who wanted to know why I asked the above question. I have the following function:
string sMessages(ArrayList aMessages, String sType) {
string sReturn = String.Empty;
if (aMessages.Count > 0) {
sReturn += "<p class=\"" + sType + "\">";
for (int i = 0; i < aMessages.Count; i++) {
sReturn += aMessages[i] + "<br />";
}
sReturn += "</p>";
}
return sReturn;
}
I send it an array of error messages and a css class which is then returned as a string for a webpage.
Every time I call this function, I have to define sType. Something like:
output += sMessages(aErrors, "errors");
As you can see, my variables is called aErrors and my css class is called errors. I was hoping my cold could figure out what class to use based on the variable name I sent it.
Again, thanks for all the responses.

thanks to visual studio 2022 , you can use this
function
public void showname(dynamic obj) {
obj.GetType().GetProperties().ToList().ForEach(state => {
NameAndValue($"{state.Name}:{state.GetValue(obj, null).ToString()}");
});
}
to use
var myname = "dddd";
showname(new { myname });

The short answer is no ... unless you are really really motivated.
The only way to do this would be via reflection and stack walking. You would have to get a stack frame, work out whereabouts in the calling function you where invoked from and then using the CodeDOM try to find the right part of the tree to see what the expression was.
For example, what if the invocation was ExampleFunction("a" + "b")?

No. A reference to your string variable gets passed to the funcion--there isn't any inherent metadeta about it included. Even reflection wouldn't get you out of the woods here--working backwards from a single reference type doesn't get you enough info to do what you need to do.
Better go back to the drawing board on this one!
rp

You could use reflection to get all the properties of an object, than loop through it, and get the value of the property where the name (of the property) matches the passed in parameter.

Well had a bit of look. of course you can't use any Type information.
Also, the name of a local variable is not available at runtime
because their names are not compiled into the assembly's metadata.

GateKiller, what's wrong with my workaround? You could rewrite your function trivially to use it (I've taken the liberty to improve the function on the fly):
static string sMessages(Expression<Func<List<string>>> aMessages) {
var messages = aMessages.Compile()();
if (messages.Count == 0) {
return "";
}
StringBuilder ret = new StringBuilder();
string sType = ((MemberExpression)aMessages.Body).Member.Name;
ret.AppendFormat("<p class=\"{0}\">", sType);
foreach (string msg in messages) {
ret.Append(msg);
ret.Append("<br />");
}
ret.Append("</p>");
return ret.ToString();
}
Call it like this:
var errors = new List<string>() { "Hi", "foo" };
var ret = sMessages(() => errors);

A way to get it can be reading the code file and splitting it with comma and parenthesis...
var trace = new StackTrace(true).GetFrame(1);
var line = File.ReadAllLines(trace.GetFileName())[trace.GetFileLineNumber()];
var argumentNames = line.Split(new[] { ",", "(", ")", ";" },
StringSplitOptions.TrimEntries)
.Where(x => x.Length > 0)
.Skip(1).ToList();

Extending on the accepted answer for this question, here is how you'd do it with #nullable enable source files:
internal static class StringExtensions
{
public static void ValidateNotNull(
[NotNull] this string? theString,
[CallerArgumentExpression("theString")] string? theName = default)
{
if (theString is null)
{
throw new ArgumentException($"'{theName}' cannot be null.", theName);
}
}
public static void ValidateNotNullOrEmpty(
[NotNull] this string? theString,
[CallerArgumentExpression("theString")] string? theName = default)
{
if (string.IsNullOrEmpty(theString))
{
throw new ArgumentException($"'{theName}' cannot be null or empty.", theName);
}
}
public static void ValidateNotNullOrWhitespace(
[NotNull] this string? theString,
[CallerArgumentExpression("theString")] string? theName = default)
{
if (string.IsNullOrWhiteSpace(theString))
{
throw new ArgumentException($"'{theName}' cannot be null or whitespace", theName);
}
}
}
What's nice about this code is that it uses [NotNull] attribute, so the static analysis will cooperate:

If I understand you correctly, you want the string "WhatIsMyName" to appear inside the Hello string.
string Hello = ExampleFunction(WhatIsMyName);
If the use case is that it increases the reusability of ExampleFunction and that Hello shall contain something like "Hello, Peter (from WhatIsMyName)", then I think a solution would be to expand the ExampleFunction to accept:
string Hello = ExampleFunction(WhatIsMyName,nameof(WhatIsMyName));
So that the name is passed as a separate string. Yes, it is not exactly what you asked and you will have to type it twice. But it is refactor safe, readable, does not use the debug interface and the chance of Error is minimal because they appear together in the consuming code.
string Hello1 = ExampleFunction(WhatIsMyName,nameof(WhatIsMyName));
string Hello2 = ExampleFunction(SomebodyElse,nameof(SomebodyElse));
string Hello3 = ExampleFunction(HerName,nameof(HerName));

No. I don't think so.
The variable name that you use is for your convenience and readability. The compiler doesn't need it & just chucks it out if I'm not mistaken.
If it helps, you could define a new class called NamedParameter with attributes Name and Param. You then pass this object around as parameters.

Related

Get both name and type of a single passed argument? [duplicate]

Let me use the following example to explain my question:
public string ExampleFunction(string Variable) {
return something;
}
string WhatIsMyName = "Hello World";
string Hello = ExampleFunction(WhatIsMyName);
When I pass the variable WhatIsMyName to the ExampleFunction, I want to be able to get a string of the original variable's name. Perhaps something like:
Variable.OriginalName.ToString() // == "WhatIsMyName"
Is there any way to do this?
What you want isn't possible directly but you can use Expressions in C# 3.0:
public void ExampleFunction(Expression<Func<string, string>> f) {
Console.WriteLine((f.Body as MemberExpression).Member.Name);
}
ExampleFunction(x => WhatIsMyName);
Note that this relies on unspecified behaviour and while it does work in Microsoft’s current C# and VB compilers, and in Mono’s C# compiler, there’s no guarantee that this won’t stop working in future versions.
This isn't exactly possible, the way you would want. C# 6.0 they Introduce the nameof Operator which should help improve and simplify the code. The name of operator resolves the name of the variable passed into it.
Usage for your case would look like this:
public string ExampleFunction(string variableName) {
//Construct your log statement using c# 6.0 string interpolation
return $"Error occurred in {variableName}";
}
string WhatIsMyName = "Hello World";
string Hello = ExampleFunction(nameof(WhatIsMyName));
A major benefit is that it is done at compile time,
The nameof expression is a constant. In all cases, nameof(...) is evaluated at compile-time to produce a string. Its argument is not evaluated at runtime, and is considered unreachable code (however it does not emit an "unreachable code" warning).
More information can be found here
Older Version Of C 3.0 and above
To Build on Nawfals answer
GetParameterName2(new { variable });
//Hack to assure compiler warning is generated specifying this method calling conventions
[Obsolete("Note you must use a single parametered AnonymousType When Calling this method")]
public static string GetParameterName<T>(T item) where T : class
{
if (item == null)
return string.Empty;
return typeof(T).GetProperties()[0].Name;
}
I know this post is really old, but since there is now a way in C#10 compiler, I thought I would share so others know.
You can now use CallerArgumentExpressionAttribute as shown
// Will throw argument exception if string IsNullOrEmpty returns true
public static void ValidateNotNullorEmpty(
this string str,
[CallerArgumentExpression("str")]string strName = null
)
{
if (string.IsNullOrEmpty(str))
{
throw new ArgumentException($"'{strName}' cannot be null or empty.", strName);
}
}
Now call with:
param.ValidateNotNullorEmpty();
will throw error: "param cannot be null or empty."
instead of "str cannot be null or empty"
static void Main(string[] args)
{
Console.WriteLine("Name is '{0}'", GetName(new {args}));
Console.ReadLine();
}
static string GetName<T>(T item) where T : class
{
var properties = typeof(T).GetProperties();
Enforce.That(properties.Length == 1);
return properties[0].Name;
}
More details are in this blog post.
Three ways:
1) Something without reflection at all:
GetParameterName1(new { variable });
public static string GetParameterName1<T>(T item) where T : class
{
if (item == null)
return string.Empty;
return item.ToString().TrimStart('{').TrimEnd('}').Split('=')[0].Trim();
}
2) Uses reflection, but this is way faster than other two.
GetParameterName2(new { variable });
public static string GetParameterName2<T>(T item) where T : class
{
if (item == null)
return string.Empty;
return typeof(T).GetProperties()[0].Name;
}
3) The slowest of all, don't use.
GetParameterName3(() => variable);
public static string GetParameterName3<T>(Expression<Func<T>> expr)
{
if (expr == null)
return string.Empty;
return ((MemberExpression)expr.Body).Member.Name;
}
To get a combo parameter name and value, you can extend these methods. Of course its easy to get value if you pass the parameter separately as another argument, but that's inelegant. Instead:
1)
public static string GetParameterInfo1<T>(T item) where T : class
{
if (item == null)
return string.Empty;
var param = item.ToString().TrimStart('{').TrimEnd('}').Split('=');
return "Parameter: '" + param[0].Trim() +
"' = " + param[1].Trim();
}
2)
public static string GetParameterInfo2<T>(T item) where T : class
{
if (item == null)
return string.Empty;
var param = typeof(T).GetProperties()[0];
return "Parameter: '" + param.Name +
"' = " + param.GetValue(item, null);
}
3)
public static string GetParameterInfo3<T>(Expression<Func<T>> expr)
{
if (expr == null)
return string.Empty;
var param = (MemberExpression)expr.Body;
return "Parameter: '" + param.Member.Name +
"' = " + ((FieldInfo)param.Member).GetValue(((ConstantExpression)param.Expression).Value);
}
1 and 2 are of comparable speed now, 3 is again sluggish.
Yes! It is possible. I have been looking for a solution to this for a long time and have finally come up with a hack that solves it (it's a bit nasty). I would not recommend using this as part of your program and I only think it works in debug mode. For me this doesn't matter as I only use it as a debugging tool in my console class so I can do:
int testVar = 1;
bool testBoolVar = True;
myConsole.Writeline(testVar);
myConsole.Writeline(testBoolVar);
the output to the console would be:
testVar: 1
testBoolVar: True
Here is the function I use to do that (not including the wrapping code for my console class.
public Dictionary<string, string> nameOfAlreadyAcessed = new Dictionary<string, string>();
public string nameOf(object obj, int level = 1)
{
StackFrame stackFrame = new StackTrace(true).GetFrame(level);
string fileName = stackFrame.GetFileName();
int lineNumber = stackFrame.GetFileLineNumber();
string uniqueId = fileName + lineNumber;
if (nameOfAlreadyAcessed.ContainsKey(uniqueId))
return nameOfAlreadyAcessed[uniqueId];
else
{
System.IO.StreamReader file = new System.IO.StreamReader(fileName);
for (int i = 0; i < lineNumber - 1; i++)
file.ReadLine();
string varName = file.ReadLine().Split(new char[] { '(', ')' })[1];
nameOfAlreadyAcessed.Add(uniqueId, varName);
return varName;
}
}
Continuing with the Caller* attribute series (i.e CallerMemberName, CallerFilePath and CallerLineNumber), CallerArgumentExpressionAttribute is available since C# Next (more info here).
The following example is inspired by Paul Mcilreavy's The CallerArgumentExpression Attribute in C# 8.0:
public static void ThrowIfNullOrWhitespace(this string self,
[CallerArgumentExpression("self")] string paramName = default)
{
if (self is null)
{
throw new ArgumentNullException(paramName);
}
if (string.IsNullOrWhiteSpace(self))
{
throw new ArgumentOutOfRangeException(paramName, self, "Value cannot be whitespace");
}
}
This would be very useful to do in order to create good exception messages causing people to be able to pinpoint errors better. Line numbers help, but you might not get them in prod, and when you do get them, if there are big statements in code, you typically only get the first line of the whole statement.
For instance, if you call .Value on a nullable that isn't set, you'll get an exception with a failure message, but as this functionality is lacking, you won't see what property was null. If you do this twice in one statement, for instance to set parameters to some method, you won't be able to see what nullable was not set.
Creating code like Verify.NotNull(myvar, nameof(myvar)) is the best workaround I've found so far, but would be great to get rid of the need to add the extra parameter.
No, but whenever you find yourself doing extremely complex things like this, you might want to re-think your solution. Remember that code should be easier to read than it was to write.
System.Environment.StackTrace will give you a string that includes the current call stack. You could parse that to get the information, which includes the variable names for each call.
Well Try this Utility class,
public static class Utility
{
public static Tuple<string, TSource> GetNameAndValue<TSource>(Expression<Func<TSource>> sourceExpression)
{
Tuple<String, TSource> result = null;
Type type = typeof (TSource);
Func<MemberExpression, Tuple<String, TSource>> process = delegate(MemberExpression memberExpression)
{
ConstantExpression constantExpression = (ConstantExpression)memberExpression.Expression;
var name = memberExpression.Member.Name;
var value = ((FieldInfo)memberExpression.Member).GetValue(constantExpression.Value);
return new Tuple<string, TSource>(name, (TSource) value);
};
Expression exception = sourceExpression.Body;
if (exception is MemberExpression)
{
result = process((MemberExpression)sourceExpression.Body);
}
else if (exception is UnaryExpression)
{
UnaryExpression unaryExpression = (UnaryExpression)sourceExpression.Body;
result = process((MemberExpression)unaryExpression.Operand);
}
else
{
throw new Exception("Expression type unknown.");
}
return result;
}
}
And User It Like
/*ToDo : Test Result*/
static void Main(string[] args)
{
/*Test : primivit types*/
long maxNumber = 123123;
Tuple<string, long> longVariable = Utility.GetNameAndValue(() => maxNumber);
string longVariableName = longVariable.Item1;
long longVariableValue = longVariable.Item2;
/*Test : user define types*/
Person aPerson = new Person() { Id = "123", Name = "Roy" };
Tuple<string, Person> personVariable = Utility.GetNameAndValue(() => aPerson);
string personVariableName = personVariable.Item1;
Person personVariableValue = personVariable.Item2;
/*Test : anonymous types*/
var ann = new { Id = "123", Name = "Roy" };
var annVariable = Utility.GetNameAndValue(() => ann);
string annVariableName = annVariable.Item1;
var annVariableValue = annVariable.Item2;
/*Test : Enum tyoes*/
Active isActive = Active.Yes;
Tuple<string, Active> isActiveVariable = Utility.GetNameAndValue(() => isActive);
string isActiveVariableName = isActiveVariable.Item1;
Active isActiveVariableValue = isActiveVariable.Item2;
}
Do this
var myVariable = 123;
myVariable.Named(() => myVariable);
var name = myVariable.Name();
// use name how you like
or naming in code by hand
var myVariable = 123.Named("my variable");
var name = myVariable.Name();
using this class
public static class ObjectInstanceExtensions
{
private static Dictionary<object, string> namedInstances = new Dictionary<object, string>();
public static void Named<T>(this T instance, Expression<Func<T>> expressionContainingOnlyYourInstance)
{
var name = ((MemberExpression)expressionContainingOnlyYourInstance.Body).Member.Name;
instance.Named(name);
}
public static T Named<T>(this T instance, string named)
{
if (namedInstances.ContainsKey(instance)) namedInstances[instance] = named;
else namedInstances.Add(instance, named);
return instance;
}
public static string Name<T>(this T instance)
{
if (namedInstances.ContainsKey(instance)) return namedInstances[instance];
throw new NotImplementedException("object has not been named");
}
}
Code tested and most elegant I can come up with.
Thanks for all the responses. I guess I'll just have to go with what I'm doing now.
For those who wanted to know why I asked the above question. I have the following function:
string sMessages(ArrayList aMessages, String sType) {
string sReturn = String.Empty;
if (aMessages.Count > 0) {
sReturn += "<p class=\"" + sType + "\">";
for (int i = 0; i < aMessages.Count; i++) {
sReturn += aMessages[i] + "<br />";
}
sReturn += "</p>";
}
return sReturn;
}
I send it an array of error messages and a css class which is then returned as a string for a webpage.
Every time I call this function, I have to define sType. Something like:
output += sMessages(aErrors, "errors");
As you can see, my variables is called aErrors and my css class is called errors. I was hoping my cold could figure out what class to use based on the variable name I sent it.
Again, thanks for all the responses.
thanks to visual studio 2022 , you can use this
function
public void showname(dynamic obj) {
obj.GetType().GetProperties().ToList().ForEach(state => {
NameAndValue($"{state.Name}:{state.GetValue(obj, null).ToString()}");
});
}
to use
var myname = "dddd";
showname(new { myname });
The short answer is no ... unless you are really really motivated.
The only way to do this would be via reflection and stack walking. You would have to get a stack frame, work out whereabouts in the calling function you where invoked from and then using the CodeDOM try to find the right part of the tree to see what the expression was.
For example, what if the invocation was ExampleFunction("a" + "b")?
No. A reference to your string variable gets passed to the funcion--there isn't any inherent metadeta about it included. Even reflection wouldn't get you out of the woods here--working backwards from a single reference type doesn't get you enough info to do what you need to do.
Better go back to the drawing board on this one!
rp
You could use reflection to get all the properties of an object, than loop through it, and get the value of the property where the name (of the property) matches the passed in parameter.
Well had a bit of look. of course you can't use any Type information.
Also, the name of a local variable is not available at runtime
because their names are not compiled into the assembly's metadata.
GateKiller, what's wrong with my workaround? You could rewrite your function trivially to use it (I've taken the liberty to improve the function on the fly):
static string sMessages(Expression<Func<List<string>>> aMessages) {
var messages = aMessages.Compile()();
if (messages.Count == 0) {
return "";
}
StringBuilder ret = new StringBuilder();
string sType = ((MemberExpression)aMessages.Body).Member.Name;
ret.AppendFormat("<p class=\"{0}\">", sType);
foreach (string msg in messages) {
ret.Append(msg);
ret.Append("<br />");
}
ret.Append("</p>");
return ret.ToString();
}
Call it like this:
var errors = new List<string>() { "Hi", "foo" };
var ret = sMessages(() => errors);
A way to get it can be reading the code file and splitting it with comma and parenthesis...
var trace = new StackTrace(true).GetFrame(1);
var line = File.ReadAllLines(trace.GetFileName())[trace.GetFileLineNumber()];
var argumentNames = line.Split(new[] { ",", "(", ")", ";" },
StringSplitOptions.TrimEntries)
.Where(x => x.Length > 0)
.Skip(1).ToList();
Extending on the accepted answer for this question, here is how you'd do it with #nullable enable source files:
internal static class StringExtensions
{
public static void ValidateNotNull(
[NotNull] this string? theString,
[CallerArgumentExpression("theString")] string? theName = default)
{
if (theString is null)
{
throw new ArgumentException($"'{theName}' cannot be null.", theName);
}
}
public static void ValidateNotNullOrEmpty(
[NotNull] this string? theString,
[CallerArgumentExpression("theString")] string? theName = default)
{
if (string.IsNullOrEmpty(theString))
{
throw new ArgumentException($"'{theName}' cannot be null or empty.", theName);
}
}
public static void ValidateNotNullOrWhitespace(
[NotNull] this string? theString,
[CallerArgumentExpression("theString")] string? theName = default)
{
if (string.IsNullOrWhiteSpace(theString))
{
throw new ArgumentException($"'{theName}' cannot be null or whitespace", theName);
}
}
}
What's nice about this code is that it uses [NotNull] attribute, so the static analysis will cooperate:
If I understand you correctly, you want the string "WhatIsMyName" to appear inside the Hello string.
string Hello = ExampleFunction(WhatIsMyName);
If the use case is that it increases the reusability of ExampleFunction and that Hello shall contain something like "Hello, Peter (from WhatIsMyName)", then I think a solution would be to expand the ExampleFunction to accept:
string Hello = ExampleFunction(WhatIsMyName,nameof(WhatIsMyName));
So that the name is passed as a separate string. Yes, it is not exactly what you asked and you will have to type it twice. But it is refactor safe, readable, does not use the debug interface and the chance of Error is minimal because they appear together in the consuming code.
string Hello1 = ExampleFunction(WhatIsMyName,nameof(WhatIsMyName));
string Hello2 = ExampleFunction(SomebodyElse,nameof(SomebodyElse));
string Hello3 = ExampleFunction(HerName,nameof(HerName));
No. I don't think so.
The variable name that you use is for your convenience and readability. The compiler doesn't need it & just chucks it out if I'm not mistaken.
If it helps, you could define a new class called NamedParameter with attributes Name and Param. You then pass this object around as parameters.

How can I get the string of a variable name passed by reference? [duplicate]

Let me use the following example to explain my question:
public string ExampleFunction(string Variable) {
return something;
}
string WhatIsMyName = "Hello World";
string Hello = ExampleFunction(WhatIsMyName);
When I pass the variable WhatIsMyName to the ExampleFunction, I want to be able to get a string of the original variable's name. Perhaps something like:
Variable.OriginalName.ToString() // == "WhatIsMyName"
Is there any way to do this?
What you want isn't possible directly but you can use Expressions in C# 3.0:
public void ExampleFunction(Expression<Func<string, string>> f) {
Console.WriteLine((f.Body as MemberExpression).Member.Name);
}
ExampleFunction(x => WhatIsMyName);
Note that this relies on unspecified behaviour and while it does work in Microsoft’s current C# and VB compilers, and in Mono’s C# compiler, there’s no guarantee that this won’t stop working in future versions.
This isn't exactly possible, the way you would want. C# 6.0 they Introduce the nameof Operator which should help improve and simplify the code. The name of operator resolves the name of the variable passed into it.
Usage for your case would look like this:
public string ExampleFunction(string variableName) {
//Construct your log statement using c# 6.0 string interpolation
return $"Error occurred in {variableName}";
}
string WhatIsMyName = "Hello World";
string Hello = ExampleFunction(nameof(WhatIsMyName));
A major benefit is that it is done at compile time,
The nameof expression is a constant. In all cases, nameof(...) is evaluated at compile-time to produce a string. Its argument is not evaluated at runtime, and is considered unreachable code (however it does not emit an "unreachable code" warning).
More information can be found here
Older Version Of C 3.0 and above
To Build on Nawfals answer
GetParameterName2(new { variable });
//Hack to assure compiler warning is generated specifying this method calling conventions
[Obsolete("Note you must use a single parametered AnonymousType When Calling this method")]
public static string GetParameterName<T>(T item) where T : class
{
if (item == null)
return string.Empty;
return typeof(T).GetProperties()[0].Name;
}
I know this post is really old, but since there is now a way in C#10 compiler, I thought I would share so others know.
You can now use CallerArgumentExpressionAttribute as shown
// Will throw argument exception if string IsNullOrEmpty returns true
public static void ValidateNotNullorEmpty(
this string str,
[CallerArgumentExpression("str")]string strName = null
)
{
if (string.IsNullOrEmpty(str))
{
throw new ArgumentException($"'{strName}' cannot be null or empty.", strName);
}
}
Now call with:
param.ValidateNotNullorEmpty();
will throw error: "param cannot be null or empty."
instead of "str cannot be null or empty"
static void Main(string[] args)
{
Console.WriteLine("Name is '{0}'", GetName(new {args}));
Console.ReadLine();
}
static string GetName<T>(T item) where T : class
{
var properties = typeof(T).GetProperties();
Enforce.That(properties.Length == 1);
return properties[0].Name;
}
More details are in this blog post.
Three ways:
1) Something without reflection at all:
GetParameterName1(new { variable });
public static string GetParameterName1<T>(T item) where T : class
{
if (item == null)
return string.Empty;
return item.ToString().TrimStart('{').TrimEnd('}').Split('=')[0].Trim();
}
2) Uses reflection, but this is way faster than other two.
GetParameterName2(new { variable });
public static string GetParameterName2<T>(T item) where T : class
{
if (item == null)
return string.Empty;
return typeof(T).GetProperties()[0].Name;
}
3) The slowest of all, don't use.
GetParameterName3(() => variable);
public static string GetParameterName3<T>(Expression<Func<T>> expr)
{
if (expr == null)
return string.Empty;
return ((MemberExpression)expr.Body).Member.Name;
}
To get a combo parameter name and value, you can extend these methods. Of course its easy to get value if you pass the parameter separately as another argument, but that's inelegant. Instead:
1)
public static string GetParameterInfo1<T>(T item) where T : class
{
if (item == null)
return string.Empty;
var param = item.ToString().TrimStart('{').TrimEnd('}').Split('=');
return "Parameter: '" + param[0].Trim() +
"' = " + param[1].Trim();
}
2)
public static string GetParameterInfo2<T>(T item) where T : class
{
if (item == null)
return string.Empty;
var param = typeof(T).GetProperties()[0];
return "Parameter: '" + param.Name +
"' = " + param.GetValue(item, null);
}
3)
public static string GetParameterInfo3<T>(Expression<Func<T>> expr)
{
if (expr == null)
return string.Empty;
var param = (MemberExpression)expr.Body;
return "Parameter: '" + param.Member.Name +
"' = " + ((FieldInfo)param.Member).GetValue(((ConstantExpression)param.Expression).Value);
}
1 and 2 are of comparable speed now, 3 is again sluggish.
Yes! It is possible. I have been looking for a solution to this for a long time and have finally come up with a hack that solves it (it's a bit nasty). I would not recommend using this as part of your program and I only think it works in debug mode. For me this doesn't matter as I only use it as a debugging tool in my console class so I can do:
int testVar = 1;
bool testBoolVar = True;
myConsole.Writeline(testVar);
myConsole.Writeline(testBoolVar);
the output to the console would be:
testVar: 1
testBoolVar: True
Here is the function I use to do that (not including the wrapping code for my console class.
public Dictionary<string, string> nameOfAlreadyAcessed = new Dictionary<string, string>();
public string nameOf(object obj, int level = 1)
{
StackFrame stackFrame = new StackTrace(true).GetFrame(level);
string fileName = stackFrame.GetFileName();
int lineNumber = stackFrame.GetFileLineNumber();
string uniqueId = fileName + lineNumber;
if (nameOfAlreadyAcessed.ContainsKey(uniqueId))
return nameOfAlreadyAcessed[uniqueId];
else
{
System.IO.StreamReader file = new System.IO.StreamReader(fileName);
for (int i = 0; i < lineNumber - 1; i++)
file.ReadLine();
string varName = file.ReadLine().Split(new char[] { '(', ')' })[1];
nameOfAlreadyAcessed.Add(uniqueId, varName);
return varName;
}
}
Continuing with the Caller* attribute series (i.e CallerMemberName, CallerFilePath and CallerLineNumber), CallerArgumentExpressionAttribute is available since C# Next (more info here).
The following example is inspired by Paul Mcilreavy's The CallerArgumentExpression Attribute in C# 8.0:
public static void ThrowIfNullOrWhitespace(this string self,
[CallerArgumentExpression("self")] string paramName = default)
{
if (self is null)
{
throw new ArgumentNullException(paramName);
}
if (string.IsNullOrWhiteSpace(self))
{
throw new ArgumentOutOfRangeException(paramName, self, "Value cannot be whitespace");
}
}
This would be very useful to do in order to create good exception messages causing people to be able to pinpoint errors better. Line numbers help, but you might not get them in prod, and when you do get them, if there are big statements in code, you typically only get the first line of the whole statement.
For instance, if you call .Value on a nullable that isn't set, you'll get an exception with a failure message, but as this functionality is lacking, you won't see what property was null. If you do this twice in one statement, for instance to set parameters to some method, you won't be able to see what nullable was not set.
Creating code like Verify.NotNull(myvar, nameof(myvar)) is the best workaround I've found so far, but would be great to get rid of the need to add the extra parameter.
No, but whenever you find yourself doing extremely complex things like this, you might want to re-think your solution. Remember that code should be easier to read than it was to write.
System.Environment.StackTrace will give you a string that includes the current call stack. You could parse that to get the information, which includes the variable names for each call.
Well Try this Utility class,
public static class Utility
{
public static Tuple<string, TSource> GetNameAndValue<TSource>(Expression<Func<TSource>> sourceExpression)
{
Tuple<String, TSource> result = null;
Type type = typeof (TSource);
Func<MemberExpression, Tuple<String, TSource>> process = delegate(MemberExpression memberExpression)
{
ConstantExpression constantExpression = (ConstantExpression)memberExpression.Expression;
var name = memberExpression.Member.Name;
var value = ((FieldInfo)memberExpression.Member).GetValue(constantExpression.Value);
return new Tuple<string, TSource>(name, (TSource) value);
};
Expression exception = sourceExpression.Body;
if (exception is MemberExpression)
{
result = process((MemberExpression)sourceExpression.Body);
}
else if (exception is UnaryExpression)
{
UnaryExpression unaryExpression = (UnaryExpression)sourceExpression.Body;
result = process((MemberExpression)unaryExpression.Operand);
}
else
{
throw new Exception("Expression type unknown.");
}
return result;
}
}
And User It Like
/*ToDo : Test Result*/
static void Main(string[] args)
{
/*Test : primivit types*/
long maxNumber = 123123;
Tuple<string, long> longVariable = Utility.GetNameAndValue(() => maxNumber);
string longVariableName = longVariable.Item1;
long longVariableValue = longVariable.Item2;
/*Test : user define types*/
Person aPerson = new Person() { Id = "123", Name = "Roy" };
Tuple<string, Person> personVariable = Utility.GetNameAndValue(() => aPerson);
string personVariableName = personVariable.Item1;
Person personVariableValue = personVariable.Item2;
/*Test : anonymous types*/
var ann = new { Id = "123", Name = "Roy" };
var annVariable = Utility.GetNameAndValue(() => ann);
string annVariableName = annVariable.Item1;
var annVariableValue = annVariable.Item2;
/*Test : Enum tyoes*/
Active isActive = Active.Yes;
Tuple<string, Active> isActiveVariable = Utility.GetNameAndValue(() => isActive);
string isActiveVariableName = isActiveVariable.Item1;
Active isActiveVariableValue = isActiveVariable.Item2;
}
Do this
var myVariable = 123;
myVariable.Named(() => myVariable);
var name = myVariable.Name();
// use name how you like
or naming in code by hand
var myVariable = 123.Named("my variable");
var name = myVariable.Name();
using this class
public static class ObjectInstanceExtensions
{
private static Dictionary<object, string> namedInstances = new Dictionary<object, string>();
public static void Named<T>(this T instance, Expression<Func<T>> expressionContainingOnlyYourInstance)
{
var name = ((MemberExpression)expressionContainingOnlyYourInstance.Body).Member.Name;
instance.Named(name);
}
public static T Named<T>(this T instance, string named)
{
if (namedInstances.ContainsKey(instance)) namedInstances[instance] = named;
else namedInstances.Add(instance, named);
return instance;
}
public static string Name<T>(this T instance)
{
if (namedInstances.ContainsKey(instance)) return namedInstances[instance];
throw new NotImplementedException("object has not been named");
}
}
Code tested and most elegant I can come up with.
Thanks for all the responses. I guess I'll just have to go with what I'm doing now.
For those who wanted to know why I asked the above question. I have the following function:
string sMessages(ArrayList aMessages, String sType) {
string sReturn = String.Empty;
if (aMessages.Count > 0) {
sReturn += "<p class=\"" + sType + "\">";
for (int i = 0; i < aMessages.Count; i++) {
sReturn += aMessages[i] + "<br />";
}
sReturn += "</p>";
}
return sReturn;
}
I send it an array of error messages and a css class which is then returned as a string for a webpage.
Every time I call this function, I have to define sType. Something like:
output += sMessages(aErrors, "errors");
As you can see, my variables is called aErrors and my css class is called errors. I was hoping my cold could figure out what class to use based on the variable name I sent it.
Again, thanks for all the responses.
thanks to visual studio 2022 , you can use this
function
public void showname(dynamic obj) {
obj.GetType().GetProperties().ToList().ForEach(state => {
NameAndValue($"{state.Name}:{state.GetValue(obj, null).ToString()}");
});
}
to use
var myname = "dddd";
showname(new { myname });
The short answer is no ... unless you are really really motivated.
The only way to do this would be via reflection and stack walking. You would have to get a stack frame, work out whereabouts in the calling function you where invoked from and then using the CodeDOM try to find the right part of the tree to see what the expression was.
For example, what if the invocation was ExampleFunction("a" + "b")?
No. A reference to your string variable gets passed to the funcion--there isn't any inherent metadeta about it included. Even reflection wouldn't get you out of the woods here--working backwards from a single reference type doesn't get you enough info to do what you need to do.
Better go back to the drawing board on this one!
rp
You could use reflection to get all the properties of an object, than loop through it, and get the value of the property where the name (of the property) matches the passed in parameter.
Well had a bit of look. of course you can't use any Type information.
Also, the name of a local variable is not available at runtime
because their names are not compiled into the assembly's metadata.
GateKiller, what's wrong with my workaround? You could rewrite your function trivially to use it (I've taken the liberty to improve the function on the fly):
static string sMessages(Expression<Func<List<string>>> aMessages) {
var messages = aMessages.Compile()();
if (messages.Count == 0) {
return "";
}
StringBuilder ret = new StringBuilder();
string sType = ((MemberExpression)aMessages.Body).Member.Name;
ret.AppendFormat("<p class=\"{0}\">", sType);
foreach (string msg in messages) {
ret.Append(msg);
ret.Append("<br />");
}
ret.Append("</p>");
return ret.ToString();
}
Call it like this:
var errors = new List<string>() { "Hi", "foo" };
var ret = sMessages(() => errors);
A way to get it can be reading the code file and splitting it with comma and parenthesis...
var trace = new StackTrace(true).GetFrame(1);
var line = File.ReadAllLines(trace.GetFileName())[trace.GetFileLineNumber()];
var argumentNames = line.Split(new[] { ",", "(", ")", ";" },
StringSplitOptions.TrimEntries)
.Where(x => x.Length > 0)
.Skip(1).ToList();
Extending on the accepted answer for this question, here is how you'd do it with #nullable enable source files:
internal static class StringExtensions
{
public static void ValidateNotNull(
[NotNull] this string? theString,
[CallerArgumentExpression("theString")] string? theName = default)
{
if (theString is null)
{
throw new ArgumentException($"'{theName}' cannot be null.", theName);
}
}
public static void ValidateNotNullOrEmpty(
[NotNull] this string? theString,
[CallerArgumentExpression("theString")] string? theName = default)
{
if (string.IsNullOrEmpty(theString))
{
throw new ArgumentException($"'{theName}' cannot be null or empty.", theName);
}
}
public static void ValidateNotNullOrWhitespace(
[NotNull] this string? theString,
[CallerArgumentExpression("theString")] string? theName = default)
{
if (string.IsNullOrWhiteSpace(theString))
{
throw new ArgumentException($"'{theName}' cannot be null or whitespace", theName);
}
}
}
What's nice about this code is that it uses [NotNull] attribute, so the static analysis will cooperate:
If I understand you correctly, you want the string "WhatIsMyName" to appear inside the Hello string.
string Hello = ExampleFunction(WhatIsMyName);
If the use case is that it increases the reusability of ExampleFunction and that Hello shall contain something like "Hello, Peter (from WhatIsMyName)", then I think a solution would be to expand the ExampleFunction to accept:
string Hello = ExampleFunction(WhatIsMyName,nameof(WhatIsMyName));
So that the name is passed as a separate string. Yes, it is not exactly what you asked and you will have to type it twice. But it is refactor safe, readable, does not use the debug interface and the chance of Error is minimal because they appear together in the consuming code.
string Hello1 = ExampleFunction(WhatIsMyName,nameof(WhatIsMyName));
string Hello2 = ExampleFunction(SomebodyElse,nameof(SomebodyElse));
string Hello3 = ExampleFunction(HerName,nameof(HerName));
No. I don't think so.
The variable name that you use is for your convenience and readability. The compiler doesn't need it & just chucks it out if I'm not mistaken.
If it helps, you could define a new class called NamedParameter with attributes Name and Param. You then pass this object around as parameters.

dynamic type does not contain a definition for 'property', error? [duplicate]

My situation is very simple. Somewhere in my code I have this:
dynamic myVariable = GetDataThatLooksVerySimilarButNotTheSame();
//How to do this?
if (myVariable.MyProperty.Exists)
//Do stuff
So, basically my question is how to check (without throwing an exception) that a certain property is available on my dynamic variable. I could do GetType() but I'd rather avoid that since I don't really need to know the type of the object. All that I really want to know is whether a property (or method, if that makes life easier) is available. Any pointers?
I think there is no way to find out whether a dynamic variable has a certain member without trying to access it, unless you re-implemented the way dynamic binding is handled in the C# compiler. Which would probably include a lot of guessing, because it is implementation-defined, according to the C# specification.
So you should actually try to access the member and catch an exception, if it fails:
dynamic myVariable = GetDataThatLooksVerySimilarButNotTheSame();
try
{
var x = myVariable.MyProperty;
// do stuff with x
}
catch (RuntimeBinderException)
{
// MyProperty doesn't exist
}
I thought I'd do a comparison of Martijn's answer and svick's answer...
The following program returns the following results:
Testing with exception: 2430985 ticks
Testing with reflection: 155570 ticks
void Main()
{
var random = new Random(Environment.TickCount);
dynamic test = new Test();
var sw = new Stopwatch();
sw.Start();
for (int i = 0; i < 100000; i++)
{
TestWithException(test, FlipCoin(random));
}
sw.Stop();
Console.WriteLine("Testing with exception: " + sw.ElapsedTicks.ToString() + " ticks");
sw.Restart();
for (int i = 0; i < 100000; i++)
{
TestWithReflection(test, FlipCoin(random));
}
sw.Stop();
Console.WriteLine("Testing with reflection: " + sw.ElapsedTicks.ToString() + " ticks");
}
class Test
{
public bool Exists { get { return true; } }
}
bool FlipCoin(Random random)
{
return random.Next(2) == 0;
}
bool TestWithException(dynamic d, bool useExisting)
{
try
{
bool result = useExisting ? d.Exists : d.DoesntExist;
return true;
}
catch (Exception)
{
return false;
}
}
bool TestWithReflection(dynamic d, bool useExisting)
{
Type type = d.GetType();
return type.GetProperties().Any(p => p.Name.Equals(useExisting ? "Exists" : "DoesntExist"));
}
As a result I'd suggest using reflection. See below.
Responding to bland's comment:
Ratios are reflection:exception ticks for 100000 iterations:
Fails 1/1: - 1:43 ticks
Fails 1/2: - 1:22 ticks
Fails 1/3: - 1:14 ticks
Fails 1/5: - 1:9 ticks
Fails 1/7: - 1:7 ticks
Fails 1/13: - 1:4 ticks
Fails 1/17: - 1:3 ticks
Fails 1/23: - 1:2 ticks
...
Fails 1/43: - 1:2 ticks
Fails 1/47: - 1:1 ticks
...fair enough - if you expect it to fail with a probability with less than ~1/47, then go for exception.
The above assumes that you're running GetProperties() each time. You may be able to speed up the process by caching the result of GetProperties() for each type in a dictionary or similar. This may help if you're checking against the same set of types over and again.
Maybe use reflection?
dynamic myVar = GetDataThatLooksVerySimilarButNotTheSame();
Type typeOfDynamic = myVar.GetType();
bool exist = typeOfDynamic.GetProperties().Where(p => p.Name.Equals("PropertyName")).Any();
Just in case it helps someone:
If the method GetDataThatLooksVerySimilarButNotTheSame() returns an ExpandoObject you can also cast to a IDictionary before checking.
dynamic test = new System.Dynamic.ExpandoObject();
test.foo = "bar";
if (((IDictionary<string, object>)test).ContainsKey("foo"))
{
Console.WriteLine(test.foo);
}
The two common solutions to this include making the call and catching the RuntimeBinderException, using reflection to check for the call, or serialising to a text format and parsing from there. The problem with exceptions is that they are very slow, because when one is constructed, the current call stack is serialised. Serialising to JSON or something analogous incurs a similar penalty. This leaves us with reflection but it only works if the underlying object is actually a POCO with real members on it. If it's a dynamic wrapper around a dictionary, a COM object, or an external web service, then reflection won't help.
Another solution is to use IDynamicMetaObjectProvider to get the member names as the DLR sees them. In the example below, I use a static class (Dynamic) to test for the Age field and display it.
class Program
{
static void Main()
{
dynamic x = new ExpandoObject();
x.Name = "Damian Powell";
x.Age = "21 (probably)";
if (Dynamic.HasMember(x, "Age"))
{
Console.WriteLine("Age={0}", x.Age);
}
}
}
public static class Dynamic
{
public static bool HasMember(object dynObj, string memberName)
{
return GetMemberNames(dynObj).Contains(memberName);
}
public static IEnumerable<string> GetMemberNames(object dynObj)
{
var metaObjProvider = dynObj as IDynamicMetaObjectProvider;
if (null == metaObjProvider) throw new InvalidOperationException(
"The supplied object must be a dynamic object " +
"(i.e. it must implement IDynamicMetaObjectProvider)"
);
var metaObj = metaObjProvider.GetMetaObject(
Expression.Constant(metaObjProvider)
);
var memberNames = metaObj.GetDynamicMemberNames();
return memberNames;
}
}
Denis's answer made me think to another solution using JsonObjects,
a header property checker:
Predicate<object> hasHeader = jsonObject =>
((JObject)jsonObject).OfType<JProperty>()
.Any(prop => prop.Name == "header");
or maybe better:
Predicate<object> hasHeader = jsonObject =>
((JObject)jsonObject).Property("header") != null;
for example:
dynamic json = JsonConvert.DeserializeObject(data);
string header = hasHeader(json) ? json.header : null;
Well, I faced a similar problem but on unit tests.
Using SharpTestsEx you can check if a property existis. I use this testing my controllers, because since the JSON object is dynamic, someone can change the name and forget to change it in the javascript or something, so testing for all properties when writing the controller should increase my safety.
Example:
dynamic testedObject = new ExpandoObject();
testedObject.MyName = "I am a testing object";
Now, using SharTestsEx:
Executing.This(delegate {var unused = testedObject.MyName; }).Should().NotThrow();
Executing.This(delegate {var unused = testedObject.NotExistingProperty; }).Should().Throw();
Using this, i test all existing properties using "Should().NotThrow()".
It's probably out of topic, but can be usefull for someone.
Following on from the answer by #karask, you could wrap the function as a helper like so:
public static bool HasProperty(ExpandoObject expandoObj,
string name)
{
return ((IDictionary<string, object>)expandoObj).ContainsKey(name);
}
For me this works:
if (IsProperty(() => DynamicObject.MyProperty))
; // do stuff
delegate string GetValueDelegate();
private bool IsProperty(GetValueDelegate getValueMethod)
{
try
{
//we're not interesting in the return value.
//What we need to know is whether an exception occurred or not
var v = getValueMethod();
return v != null;
}
catch (RuntimeBinderException)
{
return false;
}
catch
{
return true;
}
}
If you control the type being used as dynamic, couldn't you return a tuple instead of a value for every property access? Something like...
public class DynamicValue<T>
{
internal DynamicValue(T value, bool exists)
{
Value = value;
Exists = exists;
}
T Value { get; private set; }
bool Exists { get; private set; }
}
Possibly a naive implementation, but if you construct one of these internally each time and return that instead of the actual value, you can check Exists on every property access and then hit Value if it does with value being default(T) (and irrelevant) if it doesn't.
That said, I might be missing some knowledge on how dynamic works and this might not be a workable suggestion.
If your use case is to convert an api response, carrying about only a few fields, you can use this:
var template = new { address = new { street = "" } };
var response = JsonConvert.DeserializeAnonymousType(await result.Content.ReadAsStringAsync(), template);
string street = response?.address?.street;
Here is the other way:
using Newtonsoft.Json.Linq;
internal class DymanicTest
{
public static string Json = #"{
""AED"": 3.672825,
""AFN"": 56.982875,
""ALL"": 110.252599,
""AMD"": 408.222002,
""ANG"": 1.78704,
""AOA"": 98.192249,
""ARS"": 8.44469
}";
public static void Run()
{
dynamic dynamicObject = JObject.Parse(Json);
foreach (JProperty variable in dynamicObject)
{
if (variable.Name == "AMD")
{
var value = variable.Value;
}
}
}
}
In my case, I needed to check for the existence of a method with a specific name, so I used an interface for that
var plugin = this.pluginFinder.GetPluginIfInstalled<IPlugin>(pluginName) as dynamic;
if (plugin != null && plugin is ICustomPluginAction)
{
plugin.CustomPluginAction(action);
}
Also, interfaces can contain more than just methods:
Interfaces can contain methods, properties, events, indexers, or any
combination of those four member types.
From: Interfaces (C# Programming Guide)
Elegant and no need to trap exceptions or play with reflexion...
I know this is really old post but here is a simple solution to work with dynamic type in c#.
can use simple reflection to enumerate direct properties
or can use the object extention method
or use GetAsOrDefault<int> method to get a new strongly typed object with value if exists or default if not exists.
public static class DynamicHelper
{
private static void Test( )
{
dynamic myobj = new
{
myInt = 1,
myArray = new[ ]
{
1, 2.3
},
myDict = new
{
myInt = 1
}
};
var myIntOrZero = myobj.GetAsOrDefault< int >( ( Func< int > )( ( ) => myobj.noExist ) );
int? myNullableInt = GetAs< int >( myobj, ( Func< int > )( ( ) => myobj.myInt ) );
if( default( int ) != myIntOrZero )
Console.WriteLine( $"myInt: '{myIntOrZero}'" );
if( default( int? ) != myNullableInt )
Console.WriteLine( $"myInt: '{myNullableInt}'" );
if( DoesPropertyExist( myobj, "myInt" ) )
Console.WriteLine( $"myInt exists and it is: '{( int )myobj.myInt}'" );
}
public static bool DoesPropertyExist( dynamic dyn, string property )
{
var t = ( Type )dyn.GetType( );
var props = t.GetProperties( );
return props.Any( p => p.Name.Equals( property ) );
}
public static object GetAs< T >( dynamic obj, Func< T > lookup )
{
try
{
var val = lookup( );
return ( T )val;
}
catch( RuntimeBinderException ) { }
return null;
}
public static T GetAsOrDefault< T >( this object obj, Func< T > test )
{
try
{
var val = test( );
return ( T )val;
}
catch( RuntimeBinderException ) { }
return default( T );
}
}
As ExpandoObject inherits the IDictionary<string, object> you can use the following check
dynamic myVariable = GetDataThatLooksVerySimilarButNotTheSame();
if (((IDictionary<string, object>)myVariable).ContainsKey("MyProperty"))
//Do stuff
You can make a utility method to perform this check, that will make the code much cleaner and re-usable

Get GenericType-Name in good format using Reflection on C#

I need to get the name of generic-type in form of its declaration in code.
For example:
For List<Int32> I want to get string "List<Int32>".
Standart property Type.Name returns "List`1" in this situation.
EDIT: example was fixed
Using built-in functions and Linq this can be written
static string PrettyTypeName(Type t)
{
if (t.IsArray)
{
return PrettyTypeName(t.GetElementType()) + "[]";
}
if (t.IsGenericType)
{
return string.Format(
"{0}<{1}>",
t.Name.Substring(0, t.Name.LastIndexOf("`", StringComparison.InvariantCulture)),
string.Join(", ", t.GetGenericArguments().Select(PrettyTypeName)));
}
return t.Name;
}
NOTE: In pre-4.0 versions of C#, string.Join requires explicit .ToArray():
string.Join(", ", t.GetGenericArguments().Select(PrettyTypeName).ToArray()));
Ok, I've done a bunch of research, and discovered that typeof(List) has "GetGenericArguments" which will get you the sub names. So I'd do it this way (for 1 generic type, if it is a multi it'll take a loop or something. I can post a function for that if requested.
Here is a function to do it with multiple generic arguments, handles 'nested' generic types. Edited again to make this use the Aggregate function:
static string GetFullName(Type t)
{
if (!t.IsGenericType)
return t.Name;
StringBuilder sb=new StringBuilder();
sb.Append(t.Name.Substring(0, t.Name.LastIndexOf("`")));
sb.Append(t.GetGenericArguments().Aggregate("<",
delegate(string aggregate,Type type)
{
return aggregate + (aggregate == "<" ? "" : ",") + GetFullName(type);
}
));
sb.Append(">");
return sb.ToString();
}
That isn't too hard. ;-)
Okay, I'll bite... g The one below works recusively and displays primitive types w/o namespace (like the OP wrote):
static string PrettyPrintGenericTypeName(Type typeRef)
{
var rootType = typeRef.IsGenericType
? typeRef.GetGenericTypeDefinition()
: typeRef;
var cleanedName = rootType.IsPrimitive
? rootType.Name
: rootType.ToString();
if (!typeRef.IsGenericType)
return cleanedName;
else
return cleanedName.Substring(0,
cleanedName.LastIndexOf('`'))
+ typeRef.GetGenericArguments()
.Aggregate("<",
(r, i) =>
r
+ (r != "<" ? ", " : null)
+ PrettyPrintGenericTypeName(i))
+ ">";
}
The resulting cleanedName looks like this: System.Collections.Generic.Dictionary<System.Collections.Generic.List<Int32>, ConsoleApplication2.Program+SomeType>
Old question, but I only have the need for this today. So I wrote an extension method that can output nice looking C#-formatted generic name that can handle multilevel nested generic types.
using System;
using System.Text;
public static class TypeExtensions
{
public static string GetNiceName(this Type type, bool useFullName = false)
{
if (!type.IsGenericType) {
return type.Name;
}
var typeNameBuilder = new StringBuilder();
GetNiceGenericName(typeNameBuilder, type, useFullName);
return typeNameBuilder.ToString();
}
static void GetNiceGenericName(StringBuilder sb, Type type, bool useFullName)
{
if (!type.IsGenericType) {
sb.Append(useFullName ? type.FullName : type.Name);
return;
}
var typeDef = type.GetGenericTypeDefinition();
var typeName = useFullName ? typeDef.FullName : typeDef.Name;
sb.Append(typeName);
sb.Length -= typeName.Length - typeName.LastIndexOf('`');
sb.Append('<');
foreach (var typeArgument in type.GenericTypeArguments) {
GetNiceGenericName(sb, typeArgument, useFullName);
sb.Append(", ");
}
sb.Length -= 2;
sb.Append('>');
}
}
If you don't remove the namespace names, just say:
Regex.Replace(""+#type, #"`\d+\[", "<").Replace("]", ">");
and if you do, say:
Regex.Replace(Regex.Replace(""+#type, #"`\d+\[", "<").Replace("]", ">"), #"\w+\.", "")
Another example I just wrote myself before stumbling here.
private string PrettyPrintGenericTypeName(Type p)
{
if (p.IsGenericType) {
var simpleName = p.Name.Substring(0, p.Name.IndexOf('`'));
var genericTypeParams = p.GenericTypeArguments.Select(PrettyPrintGenericTypeName).ToList();
return string.Format("{0}<{1}>", simpleName, string.Join(", ", genericTypeParams));
} else {
return p.Name;
}
}
Well, that's because the name of the type in .NET actually IS List'1. The "'1" is the so called arity of the generic, and it tells you how many type parameters there are.
It's needed so that you can create more then 1 generic type with the same "name" but a different number of generic type parameters.
For example, there are more than 1 type "called" System.Action. The real names of these are System.Action'1, System.Action'2, System.Action'3 etc.
So, if you know that your type is generic, you can assume that there is this 'XX at the end of the name, so you could just cut this part away, for example like this:
string strTypeName = typeof(List<>).Name.Substring(0, typeof(List<>).Name.LastIndexOf("`"));
PS: Please replace ' with `.

What is the best way to dump entire objects to a log in C#?

So for viewing a current object's state at runtime, I really like what the Visual Studio Immediate window gives me. Just doing a simple
? objectname
Will give me a nicely formatted 'dump' of the object.
Is there an easy way to do this in code, so I can do something similar when logging?
For a larger object graph, I second the use of Json but with a slightly different strategy. First I have a static class that is easy to call and with a static method that wraps the Json conversion (note: could make this an extension method).
using Newtonsoft.Json;
public static class F
{
public static string Dump(object obj)
{
return JsonConvert.SerializeObject(obj);
}
}
Then in your Immediate Window,
var lookHere = F.Dump(myobj);
lookHere will auto-show up in the Locals window prepended with a $ or you can add a watch to it. On the right hand side of the Value column in the inspector, there is a magnifying glass with a dropdown caret beside it. Choose the dropdown caret and choose Json visualizer.
I am using Visual Studio 2013.
You could base something on the ObjectDumper code that ships with the Linq samples.
Have also a look at the answer of this related question to get a sample.
You could use Visual Studio Immediate Window
Just paste this (change actual to your object name obviously):
Newtonsoft.Json.JsonConvert.SerializeObject(actual);
It should print object in JSON
You should be able to copy it over textmechanic text tool or notepad++ and replace escaped quotes (\") with " and newlines (\r\n) with empty space, then remove double quotes (") from beginning and end and paste it to jsbeautifier to make it more readable.
UPDATE to OP's comment
public static class Dumper
{
public static void Dump(this object obj)
{
Console.WriteLine(Newtonsoft.Json.JsonConvert.SerializeObject(obj)); // your logger
}
}
this should allow you to dump any object.
Hope this saves you some time.
I'm certain there are better ways of doing this, but I have in the past used a method something like the following to serialize an object into a string that I can log:
private string ObjectToXml(object output)
{
string objectAsXmlString;
System.Xml.Serialization.XmlSerializer xs = new System.Xml.Serialization.XmlSerializer(output.GetType());
using (System.IO.StringWriter sw = new System.IO.StringWriter())
{
try
{
xs.Serialize(sw, output);
objectAsXmlString = sw.ToString();
}
catch (Exception ex)
{
objectAsXmlString = ex.ToString();
}
}
return objectAsXmlString;
}
You'll see that the method might also return the exception rather than the serialized object, so you'll want to ensure that the objects you want to log are serializable.
ServiceStack.Text has a T.Dump() extension method that does exactly this, recursively dumps all properties of any type in a nice readable format.
Example usage:
var model = new TestModel();
Console.WriteLine(model.Dump());
and output:
{
Int: 1,
String: One,
DateTime: 2010-04-11,
Guid: c050437f6fcd46be9b2d0806a0860b3e,
EmptyIntList: [],
IntList:
[
1,
2,
3
],
StringList:
[
one,
two,
three
],
StringIntMap:
{
a: 1,
b: 2,
c: 3
}
}
Here is a stupidly simple way to write a flat object, nicely formatted:
using Newtonsoft.Json.Linq;
Debug.WriteLine("The object is " + JObject.FromObject(theObjectToDump).ToString());
What's going on is that the object is first converted to a JSON internal representation by JObject.FromObject, and then converted to JSON string by ToString. (And of course a JSON string is a very nice representation of a simple object, especially since ToString will include newlines and indents.) The "ToString" is of course extraneous (as it's implied by using + to concat a string and an object), but I kinda like to specify it here.
You could use reflection and loop through all the object properties, then get their values and save them to the log. The formatting is really trivial (you could use \t to indent an objects properties and its values):
MyObject
Property1 = value
Property2 = value2
OtherObject
OtherProperty = value ...
What I like doing is overriding ToString() so that I get more useful output beyond the type name. This is handy in the debugger, you can see the information you want about an object without needing to expand it.
Following is another version that does the same thing (and handle nested properties), which I think is simpler (no dependencies on external libraries and can be modified easily to do things other than logging):
public class ObjectDumper
{
public static string Dump(object obj)
{
return new ObjectDumper().DumpObject(obj);
}
StringBuilder _dumpBuilder = new StringBuilder();
string DumpObject(object obj)
{
DumpObject(obj, 0);
return _dumpBuilder.ToString();
}
void DumpObject(object obj, int nestingLevel = 0)
{
var nestingSpaces = "".PadLeft(nestingLevel * 4);
if (obj == null)
{
_dumpBuilder.AppendFormat("{0}null\n", nestingSpaces);
}
else if (obj is string || obj.GetType().IsPrimitive)
{
_dumpBuilder.AppendFormat("{0}{1}\n", nestingSpaces, obj);
}
else if (ImplementsDictionary(obj.GetType()))
{
using (var e = ((dynamic)obj).GetEnumerator())
{
var enumerator = (IEnumerator)e;
while (enumerator.MoveNext())
{
dynamic p = enumerator.Current;
var key = p.Key;
var value = p.Value;
_dumpBuilder.AppendFormat("{0}{1} ({2})\n", nestingSpaces, key, value != null ? value.GetType().ToString() : "<null>");
DumpObject(value, nestingLevel + 1);
}
}
}
else if (obj is IEnumerable)
{
foreach (dynamic p in obj as IEnumerable)
{
DumpObject(p, nestingLevel);
}
}
else
{
foreach (PropertyDescriptor descriptor in TypeDescriptor.GetProperties(obj))
{
string name = descriptor.Name;
object value = descriptor.GetValue(obj);
_dumpBuilder.AppendFormat("{0}{1} ({2})\n", nestingSpaces, name, value != null ? value.GetType().ToString() : "<null>");
DumpObject(value, nestingLevel + 1);
}
}
}
bool ImplementsDictionary(Type t)
{
return t.GetInterfaces().Any(i => i.Name.Contains("IDictionary"));
}
}
I found a library called ObjectPrinter which allows to easily dump objects and collections to strings (and more). It does exactly what I needed.
You can write your own WriteLine method-
public static void WriteLine<T>(T obj)
{
var t = typeof(T);
var props = t.GetProperties();
StringBuilder sb = new StringBuilder();
foreach (var item in props)
{
sb.Append($"{item.Name}:{item.GetValue(obj,null)}; ");
}
sb.AppendLine();
Console.WriteLine(sb.ToString());
}
Use it like-
WriteLine(myObject);
To write a collection we can use-
var ifaces = t.GetInterfaces();
if (ifaces.Any(o => o.Name.StartsWith("ICollection")))
{
dynamic lst = t.GetMethod("GetEnumerator").Invoke(obj, null);
while (lst.MoveNext())
{
WriteLine(lst.Current);
}
}
The method may look like-
public static void WriteLine<T>(T obj)
{
var t = typeof(T);
var ifaces = t.GetInterfaces();
if (ifaces.Any(o => o.Name.StartsWith("ICollection")))
{
dynamic lst = t.GetMethod("GetEnumerator").Invoke(obj, null);
while (lst.MoveNext())
{
WriteLine(lst.Current);
}
}
else if (t.GetProperties().Any())
{
var props = t.GetProperties();
StringBuilder sb = new StringBuilder();
foreach (var item in props)
{
sb.Append($"{item.Name}:{item.GetValue(obj, null)}; ");
}
sb.AppendLine();
Console.WriteLine(sb.ToString());
}
}
Using if, else if and checking interfaces, attributes, base type, etc. and recursion (as this is a recursive method) in this way we may achieve an object dumper, but it is tedious for sure. Using the object dumper from Microsoft's LINQ Sample would save your time.
All of the paths above assume that your objects are serializable to XML or JSON,
or you must implement your own solution.
But in the end you still get to the point where you have to solve problems like
recursion in objects
non-serializable objects
exceptions
...
Plus log you want more information:
when the event happened
callstack
which threead
what was in the web session
which ip address
url
...
There is the best solution that solves all of this and much more.
Use this Nuget package: Desharp.
For all types of applications - both web and desktop applications.
See it's Desharp Github documentation. It has many configuration options.
Just call anywhere:
Desharp.Debug.Log(anyException);
Desharp.Debug.Log(anyCustomValueObject);
Desharp.Debug.Log(anyNonserializableObject);
Desharp.Debug.Log(anyFunc);
Desharp.Debug.Log(anyFunc, Desharp.Level.EMERGENCY); // you can store into different files
it can save the log in nice HTML (or in TEXT format, configurable)
it's possible to write optionally in background thread (configurable)
it has options for max objects depth and max strings length (configurable)
it uses loops for iteratable objects and backward reflection for everything else,
indeed for anything you can find in .NET environment.
I believe it will help.
So far a simplest and tidiest way for me is a serializer from YamlDotNet package.
using YamlDotNet.Serialization;
List<string> strings=new List<string>{"a","b","c"};
new Serializer().Serialize(strings)
will give you
- a
- b
- c
A more comprehensive example is here https://dotnetfiddle.net/KuV63n
Today you don't even need an external dependency. You can just use the built-in Microsoft Json Serializer.
using System;
using System.Text.Json;
namespace MyCompany.Core.Extensions
{
public static class ObjectExtensions
{
public static string Dump(this object obj)
{
try
{
return JsonSerializer.Serialize(obj);
}
catch(Exception)
{
return string.Empty;
}
}
}
}
Notice that you can pass a JsonSerializerOptions parameter to further customize the serialization to your liking:
Let's say you want to write the JSON indented for easy reading... we'd use:
new JsonSerializerOptions { WriteIndented = true }
#######
Here's a good guide if you wish to migrate from NewtonSoft.Json to System.Text.Json:
Compare Newtonsoft.Json to System.Text.Json, and migrate to System.Text.Json
Based on #engineforce answer, I made this class that I'm using in a PCL project of a Xamarin Solution:
/// <summary>
/// Based on: https://stackoverflow.com/a/42264037/6155481
/// </summary>
public class ObjectDumper
{
public static string Dump(object obj)
{
return new ObjectDumper().DumpObject(obj);
}
StringBuilder _dumpBuilder = new StringBuilder();
string DumpObject(object obj)
{
DumpObject(obj, 0);
return _dumpBuilder.ToString();
}
void DumpObject(object obj, int nestingLevel)
{
var nestingSpaces = "".PadLeft(nestingLevel * 4);
if (obj == null)
{
_dumpBuilder.AppendFormat("{0}null\n", nestingSpaces);
}
else if (obj is string || obj.GetType().GetTypeInfo().IsPrimitive || obj.GetType().GetTypeInfo().IsEnum)
{
_dumpBuilder.AppendFormat("{0}{1}\n", nestingSpaces, obj);
}
else if (ImplementsDictionary(obj.GetType()))
{
using (var e = ((dynamic)obj).GetEnumerator())
{
var enumerator = (IEnumerator)e;
while (enumerator.MoveNext())
{
dynamic p = enumerator.Current;
var key = p.Key;
var value = p.Value;
_dumpBuilder.AppendFormat("{0}{1} ({2})\n", nestingSpaces, key, value != null ? value.GetType().ToString() : "<null>");
DumpObject(value, nestingLevel + 1);
}
}
}
else if (obj is IEnumerable)
{
foreach (dynamic p in obj as IEnumerable)
{
DumpObject(p, nestingLevel);
}
}
else
{
foreach (PropertyInfo descriptor in obj.GetType().GetRuntimeProperties())
{
string name = descriptor.Name;
object value = descriptor.GetValue(obj);
_dumpBuilder.AppendFormat("{0}{1} ({2})\n", nestingSpaces, name, value != null ? value.GetType().ToString() : "<null>");
// TODO: Prevent recursion due to circular reference
if (name == "Self" && HasBaseType(obj.GetType(), "NSObject"))
{
// In ObjC I need to break the recursion when I find the Self property
// otherwise it will be an infinite recursion
Console.WriteLine($"Found Self! {obj.GetType()}");
}
else
{
DumpObject(value, nestingLevel + 1);
}
}
}
}
bool HasBaseType(Type type, string baseTypeName)
{
if (type == null) return false;
string typeName = type.Name;
if (baseTypeName == typeName) return true;
return HasBaseType(type.GetTypeInfo().BaseType, baseTypeName);
}
bool ImplementsDictionary(Type t)
{
return t is IDictionary;
}
}
Option 1: CSharpObjectFormatter from the Microsoft.CodeAnalysis.CSharp.Scripting.
C# REPL Command-Line Interface (CSI.EXE) and CSharpRepl use exactly this formatter.
using Microsoft.CodeAnalysis.CSharp.Scripting.Hosting;
var students = new[]
{
new Student
{
Id = 1,
Name = "Michael Hilus"
},
new Student
{
Id = 2,
Name = "Alicia Keys"
}
};
var formattedStudents = CSharpObjectFormatter.Instance.FormatObject(students);
Console.WriteLine(formattedStudents);
Output:
Student[2] { Student { Id=1, Name="Michael Hilus" }, Student { Id=2, Name="Alicia Keys" } }
But it's suitable for relatively simple objects, for example it can't dump the instance of System.Data.DataTable.
Option 2: vm.Aspects.Diagnostics.ObjectTextDumper - see documentation.
There is also very popular library:
ObjectDumper.NET, it's an open source, but not free for commercial use.

Categories

Resources