是否可以从nameof(VALUE)获取VALUE?

时间:2019-04-11 14:10:29

标签: c#

我正在记录异常。现在,我可以抛出带有任何参数的异常,并将其提供给log方法。我想在日志消息中显示每个参数的名称,类型和值。类型和值没有问题,但是我无法获取变量的名称。我不想将参数数量加倍,在抛出时为每个参数添加nameof(Value)。

这就是我使用不同参数抛出的方式:

        throw new TestException(new object[]{ var0,
                                              var1,
                                              var2,
                                              var3,
                                              var4 });

这是我不想扔给他们的方式:

        throw new TestException(new object[]{ var0, nameof(var0)
                                              var1, nameof(var1)
                                              var2, nameof(var2)
                                              var3, nameof(var3)
                                              var4, nameof(var4) });

这些是我对将数据包装到对象中的想法:

public class ArgWrapper
{
    public ArgWrapper()
    {

    }

    public string Type { get; set; }
    public string Name { get; set; }
    public object Value { get; set; }
}

因此,我希望收集具有此类字段的对象,因此我将记录有关每个参数的信息,例如:{类型:“类型”,名称:“名称”,值:“值”}

3 个答案:

答案 0 :(得分:3)

您需要使用GetProperties(),该方法将返回所有属性

object example  = new {si= DateTime.Now, no= "no"}; //object example

var typevar  = example.GetType().GetProperties(); //get all te props
//lets loop all the props because it GetProperties() return all props
foreach(var i in typevar){
     //if is DateTime well write the name of prop with i.Name 
     Console.WriteLine("The prop {0} is date time", i.Name);

}

答案 1 :(得分:1)

向ArgWrapper类添加一个方法,该方法可以从参数的表达式中检索所需的信息。像这样:

public class ArgWrapper
{
    public static ArgWrapper Create<T>(Expression<Func<T>> expression)
    {
        T valueAsT = expression.Compile()();
        string value = Convert.ToString(valueAsT, CultureInfo.InvariantCulture);

        // Get type name
        string type = valueAsT?.GetType().FullName ?? "null";

        string name = "";

        // Get name by traversing memberexpressions from right to left
        MemberExpression memberExpression = expression.Body as MemberExpression;
        Expression traverseExpression = expression.Body;
        while (traverseExpression != null && traverseExpression is MemberExpression)
        {
            memberExpression = traverseExpression as MemberExpression;
            name = memberExpression.Member.Name + "." + name;
            traverseExpression = memberExpression.Expression;
        }

        // If the last memberexpression has no expression, this is a global class name, we want to include
        if (traverseExpression == null && memberExpression != null)
        {
            name = memberExpression.Member.DeclaringType.Name + "." + name;
        }

        var argWrapper = new ArgWrapper();
        argWrapper.Name = name;
        argWrapper.Type = type;
        argWrapper.Value = value;

        return argWrapper;
    }

    public string Type { get; set; }
    public string Name { get; set; }
    public object Value { get; set; }
}

如果这是您的异常类

public class TestException : Exception
{
    private List<ArgWrapper> parameters = new List<ArgWrapper>();
    public IEnumerable<ArgWrapper> Parameters => parameters;

    public TestException(params ArgWrapper[] passedParameters)
    {
        parameters.AddRange(passedParameters);
    }
}

然后您可以像这样使用它

private void button1_Click(object sender, EventArgs e)
{
    string s = "Hello World";
    double pi = Math.PI;
    string nullString = null;

    var exception = new TestException(
        ArgWrapper.Create(() => 42),
        ArgWrapper.Create(() => s),
        ArgWrapper.Create(() => s.Length),
        ArgWrapper.Create(() => pi),
        ArgWrapper.Create(() => button1.Text),
        ArgWrapper.Create(() => Application.CurrentCulture.Calendar.AlgorithmType),
        ArgWrapper.Create(() => DateTime.Now),
        ArgWrapper.Create(() => nullString)
        );


    foreach(var param in exception.Parameters)
    {
        Console.WriteLine($"{param.Name} - {param.Type} - {param.Value}");
    }

}

将产生以下输出:

 - System.Int32 - 42
s. - System.String - Hello World
s.Length. - System.Int32 - 11
pi. - System.Double - 3.14159265358979
button1.Text. - System.String - button1
Application.CurrentCulture.Calendar.AlgorithmType. - System.Globalization.CalendarAlgorithmType - SolarCalendar
DateTime.Now. - System.DateTime - 04/11/2019 18:23:42
nullString. - null - 

答案 2 :(得分:-1)

第一部分是正确的。 您需要将这些属性定义为公共属性,并且需要知道包含这些属性的对象!

public Object TestProperty { get; set; } = "test";

private void GetFromName()
{
   var properties = this.GetType().GetProperties();
   var foundProperty = properties.ToList().Find(property => property.Name == /* nameof(x) string */);

   var test = foundProperty.GetValue(/* object containing the property */);
}