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

问题描述 投票:2回答:3

我正在记录异常。现在我有能力抛出任何参数的异常并将它们提供给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; }
}

因此,我希望拥有包含此类字段的对象集合,因此我将记录有关每个参数的信息,如:{Type:“type”,Name:“name”,Value:“value”}

c#
3个回答
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
投票

向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 - 

-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 */);
}
© www.soinside.com 2019 - 2024. All rights reserved.