C# 获取属性的名称并声明类

C# 获取属性的名称并声明类,c#,generics,reflection,C#,Generics,Reflection,如何使用反射获取泛型类型属性的名称和声明类。这样做的目的是,如果我读取了一个到目前为止还没有写入任何内容的属性,则会得到一个异常。问题之一是检查必须独立于声明类 value.GetType.DeclaringType始终为null 不,你不能那样做。我建议这样做: // You could do this without the constraint, with a bit of extra work. public class ReadOnlyAfterWrite<T> where

如何使用反射获取泛型类型属性的名称和声明类。这样做的目的是,如果我读取了一个到目前为止还没有写入任何内容的属性,则会得到一个异常。问题之一是检查必须独立于声明类

value.GetType.DeclaringType始终为null


不,你不能那样做。我建议这样做:

// You could do this without the constraint, with a bit of extra work.
public class ReadOnlyAfterWrite<T> where T : struct
{
    private T? value;
    private readonly string property;
    private readonly string type;

    public ReadOnlyAfterWrite(string property, string type)
    {
        this.property = property;
        this.type = type;
    }

    public T Value
    {
        get
        {
            if (value == null)
            {
                // Use type and property here
                throw new InvalidOperationException(...);
            }
            return (T) value;
        }
        set { this.value = value; }
    }
}

public class ContractClass
{
    // This is what I'd do in C# 6. Before that, probably just use string literals.
    private readonly ReadOnlyAfterWrite<int> delta =
        new ReadOnlyAfterWrite(nameof(Delta), nameof(ContractClass));

    public int Delta
    {
        get { return delta.Value; }
        set { delta.Value = value; }
    }
}
虽然它在实现上不是非常干净,但我认为它是一个更好的公共API——它被保护的事实对调用方是不可见的,调用方只看到int属性

// You could do this without the constraint, with a bit of extra work.
public class ReadOnlyAfterWrite<T> where T : struct
{
    private T? value;
    private readonly string property;
    private readonly string type;

    public ReadOnlyAfterWrite(string property, string type)
    {
        this.property = property;
        this.type = type;
    }

    public T Value
    {
        get
        {
            if (value == null)
            {
                // Use type and property here
                throw new InvalidOperationException(...);
            }
            return (T) value;
        }
        set { this.value = value; }
    }
}

public class ContractClass
{
    // This is what I'd do in C# 6. Before that, probably just use string literals.
    private readonly ReadOnlyAfterWrite<int> delta =
        new ReadOnlyAfterWrite(nameof(Delta), nameof(ContractClass));

    public int Delta
    {
        get { return delta.Value; }
        set { delta.Value = value; }
    }
}