动态创建属性

时间:2016-04-21 02:40:56

标签: c# linq reflection

所以我有一个包含许多属性的对象,PropertyNameYear1PropertyNameYear2PropertyNameYear3 ...已有20年。这些属性可能会随着时间的推移而增长,因此将来我可能需要添加PropertyNameYear21等等。

我正在尝试获取这些属性,包括它们的名称和值,而不指定每个属性,因为从理论上讲,我可以拥有数十个属性。我可以使用LINQ和Object Initializer来做,但是我必须指定每个属性两次

new {
    PropertyNameYear1 = f => f.PropertyNameYear1,
    PropertyNameYear2 = f => f.PropertyNameYear2,
    ...
};

如何使用LINQ(和Refelction?)将所有这些属性(只有这些属性,假设有其他属性与PropertyNameYearX不同)获取到新的/另一个对象并返回该对象? / p>

这是我正在寻找的伪代码:

public ReturnType GetSomeObjectWithSpecificProperties(int ID){
    var list = SomeObjectRepository.Where(f => f.ID == ID);
    var props = list.GetType().GetProperties().ToList();
    var SomePropObjectList = props.Where(f => f.Name.Contains("PropertyNameYear")).ToList();

    var listToReturn = SomePropObjectList.Select(f => new {
        f.Name = f.GetValue(list)
    }).ToList();

    return listToReturn;
}

2 个答案:

答案 0 :(得分:4)

我想说明你应该重新考虑你的做法。

而不是:

public class NotGood
{
    public int PropertyNameYear1{ get; set; }
    //repeat 20 times...
    public int PropertyNameYear21{ get; set; }
}

...考虑:

public class Better
{
    public List<int> PropertyNameYears{ get; } = new List<int>();
}

这是一行代码,它会扩展得更好。另外,你消除了所有笨拙的,基于反射的解析。

编辑:正如我在评论中提到的,有时清理代码的正确方法是与作者讨论错误的代码而不是调整代码以适应他们引起的问题,但如果没有解决方法,这里的方法是需要四行代码:

var obj = new
{
    SomeNormalProp = "foo",
    ThisIsSilly1 = 1,
    ThisIsSilly2 = 2,
    ThisIsSilly3 = 3,
    ThisIsSilly4 = 4
};

dynamic barfObj = new ExpandoObject();
foreach (var prop in obj.GetType().GetProperties())
    if (prop.Name.StartsWith("ThisIsSilly"))
        //add property dynamically
        ((IDictionary<string, object>)barfObj).Add(prop.Name, prop.GetValue(obj));

//now barfObj is exactly what you want.
var sampleVal = barfObj.ThisIsSilly1;
var json = JsonConvert.SerializeObject(barfObj);

或者,如果你是一个真正的受虐狂,你有Reflection.Emit: How to dynamically create a class in C#?

答案 1 :(得分:0)

您可以使用ExpandoObject从源类对象动态添加属性。假设源类是ClassWithMayProperties:

    public object GetObject(ClassWithManyPropererties obj)
    {
        var props = obj.GetType().GetProperties().Where(p => p.Name.Contains("PropertyNameYear")).ToList();

        dynamic returnObject = new ExpandoObject() as IDictionary<string, Object>;

        foreach (var property in props)
        {
            returnObject.Add(property.Name, property.GetValue(obj));
        }

        return returnObject;
    }

然后,您可以直接获取所需属性的值,或者在IDictionary中强制使用ExpandoObject,并检查属性名称是否为键。

        var dynObject = GetObject(obj);
        var d  = dynObject.PropertyNameYear1