C# 动态创建属性

C# 动态创建属性,c#,linq,reflection,C#,Linq,Reflection,所以我有一个有很多属性的对象,PropertyNameYear1,PropertyNameYear2,PropertyNameYear3…持续了20年。这些属性可能会随着时间的推移而增长,因此将来我可能需要添加PropertyNameYear21等等 我试图获得这些属性,包括它们的名称和值,而不指定每一个,因为理论上我可以有几十个。我可以使用LINQ和对象初始值设定项来完成,但是我必须指定每个属性两次: 假设存在其他与PropertyNameYearX命名不同的属性,我如何使用LINQ和Refe

所以我有一个有很多属性的对象,PropertyNameYear1,PropertyNameYear2,PropertyNameYear3…持续了20年。这些属性可能会随着时间的推移而增长,因此将来我可能需要添加PropertyNameYear21等等

我试图获得这些属性,包括它们的名称和值,而不指定每一个,因为理论上我可以有几十个。我可以使用LINQ和对象初始值设定项来完成,但是我必须指定每个属性两次:

假设存在其他与PropertyNameYearX命名不同的属性,我如何使用LINQ和Refelction?将所有这些属性和仅这些属性获取到一个新/另一个对象中并返回该对象

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

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;
}
您可以使用ExpandooObject从源类对象动态添加属性。假设源类是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;
    }
您可以使用ExpandooObject从源类对象动态添加属性。假设源类是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;
    }

我想插一句,说你应该重新考虑你的方法

而不是:

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);
或者如果你是一个真正的受虐狂,你有反射。发射:
我想插一句,说你应该重新考虑你的方法

而不是:

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);
或者如果你是一个真正的受虐狂,你有反射。发射:

当然,这是一种更好的方法。但是假设我对这个物体没有控制权,你认识那个控制这个物体的人吗?你能往后推吗?有时候,正确的编写好代码的方法超越了代码本身,涉及到与其他开发人员之间的一些来回交流,这些开发人员可以从代码审查中获益。我在寻找如何这样做。有什么方法可以实现我所追求的吗?例如,在JS中,它相当简单。在.NET中,使用dynamic、ExpandoObject或Newtonsoft.JSON也相对简单,但我仍然建议尽可能取消设计。不过,请看经过调整的答案,看看它是如何工作的。因此,我对尼廷发表了评论。这将提供一个键/值对象,而不是一个具有属性的对象,当然,这是一种更好的方法。但是假设我对这个物体没有控制权,你认识那个控制这个物体的人吗?你能往后推吗?有时候,正确的编写好代码的方法超越了代码本身,涉及到与其他开发人员之间的一些来回交流,这些开发人员可以从代码审查中获益。我在寻找如何这样做。有什么方法可以实现我所追求的吗?例如,在JS中,它相当简单。在.NET中,使用dynamic、ExpandoObject或Newtonsoft.JSON也相对简单,但我仍然建议尽可能取消设计。不过,请看经过调整的答案,看看它是如何工作的。因此,我对尼廷发表了评论。这将提供一个键/值对象,而不是一个具有属性的对象,这将生成一个KeyValuePair列表,其中该列表中的每个项都是{key:PropertyNameYear1,value:Val}。我正在尝试获取一个{PropertNameYear1:Val}列表,这将生成一个KeyValuePair列表,其中该列表中的每个项都是{Key:PropertyNameYear1,Value:Val}。我正在尝试获取{PropertNameYear1:Val}的列表