通用类检查初始化了哪些属性

时间:2015-12-15 14:25:32

标签: c# generics

有没有办法从实例化的类中检查哪些属性最初设置了?

正如您在示例中所看到的,我可以检查字符串数据类型的“null”值,但我无法检查int值,因为默认值为“0”。

有没有办法检查属性是否设置在对象的“实例化时间”?

我希望能够将任何类传递给“ParseProperties”类。

检查此示例:

class Program
{
    static void Main(string[] args)
    {
        // The following foreach gives me the output as follows
        // Actual output:
        // Id
        // Name
        // Age
        //
        // Desired output:
        // John
        foreach (string initiatedPropery in ParseProperties(new Person { Name = "John" }))
        {
            Console.WriteLine(initiatedPropery);
        }
        // The following foreach gives me the output as follows
        // Actual output:
        // Id
        // Age
        //
        // Desired output:
        // Id
        foreach (string initiatedPropery in ParseProperties(new Person { Id = 45 }))
        {
            Console.WriteLine(initiatedPropery);
        }
        Console.ReadLine();
    }

    private static List<string> ParseProperties<T>(T obj)
    {
        var initiatedProperties = new List<string>();
        var properties = typeof(T).GetProperties();
        foreach (var property in properties)
        {
            // For strings I can check if property is null but I can't check for int's if they were set. How could I do that?                
            var value = typeof(T).GetProperty(property.Name).GetValue(obj, null);
            if (value != null) // --> I would need to get somehow if a property was initially set or not
            {
                initiatedProperties.Add(property.Name);
            }
        }
        return initiatedProperties;
    }

    private class Person
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public int Age { get; set; }
    }
}

2 个答案:

答案 0 :(得分:2)

鉴于这样的课程:

private class Person
{
    public int Id { get; set; }
    public string Name { get; set; }
    public int Age { get; set; }
}

实际上没有办法处理这个一般,它不涉及对类本身的一些更改。在不更改您用作泛型类型参数的类的情况下,您可以做的最好的事情就像比较myProp == default(S),其中S是属性的类型。这将告诉您可能属性尚未初始化。

如果您可以更改作为通用参数传递的类,那么您有更多选项。最简单的是:

public int? Age { get; set; }

现在Age属性为null而不是0

另一种策略是让另一个属性告诉你是否设置了Age

public bool AgeWasSet { get; private set; }
private int _age;
public int Age 
{
    get { return _age; }
    set { _age = value; AgeWasSet = true; }
}

你可以使用像 propName WasSet这样的约定作为属性来识别哪个属性与哪个属性相关(这不是闻所未闻的,例如JSON.Net将寻找具有该名称的属性ShouldSerialize propName 是一种将一些逻辑注入序列化的方法。

最后,您可以执行类似基类或界面定义方法的操作,以便为您提供所需的信息。类似的东西:

public interface IFieldInitializationInfo
{
    string[] GetUninitializedFields();    // or maybe PropertyInfo[]
}

然后你的类可以实现该接口,并根据你想要用于特定类的逻辑来报告哪些字段没有被初始化。

答案 1 :(得分:1)

  

有没有办法检查属性是否设置为&#34; instantiation-time&#34;对象?

无视使用int?int进行&#34;未初始化&#34;整数,无法判断是否在初始值设定项中设置了值。初始化程序相当于在构造后设置属性,因此

Person p = new Person() {Id = 4};

完全相同
Person p = new Person();
p.Id = 4;

如果你要求在构造对象时设置某些属性,那么使用构造函数

public Person(int id)
{
   Id = id;
}