如何在c#中编辑对象列表动态

时间:2017-06-09 17:43:17

标签: c# dynamic

C#中的示例:

List<dynamic> ListaPersonas = new List<dynamic>() {
    new { valor= 1,Nombre="maria"},
    new { valor= 2,Nombre="jose"},
    new { valor =3,Nombre="juan"}
};          

foreach (var item in ListaPersonas)
    if (item.Nombre == "jose")
        item.valor = 7;

错误

  

无法分配属性或索引器'<> f__AnonymousType0 <int, string> .value',因为它是只读的

我有一个包含数据的列表,我必须通过它并应用验证,这会导致某些值被修改。实现这一目标的最佳方法是什么?

3 个答案:

答案 0 :(得分:0)

问题是 ListaPersonas 获取只读的匿名对象列表。

  

ListaPersonas [0] .GetType()。名称

上面的代码返回AnonymousType。因此,我们将通过创建扩展类将列表转换为动态List<ExpandoObject>

将您的代码更改为:

    dynamic ListaPersonas = (new List<dynamic>() {
        new { valor= 1,Nombre="maria"},
        new { valor= 2,Nombre="jose"},
        new { valor =3,Nombre="juan"}
    }).ToDynamic();

    foreach (var item in ListaPersonas)
        if (item.Nombre == "jose")
            item.valor = 7;

将此课程添加到您的项目

public static class DynamicExtensions
{
    public static dynamic ToDynamic(this object value)
    {

        var list = new List<ExpandoObject>();
        foreach (var item in (List<dynamic>)value)
        {
            IDictionary<string, object> expando = new ExpandoObject();
            foreach (PropertyDescriptor property in TypeDescriptor.GetProperties(item.GetType()))
            {
                expando.Add(property.Name, property.GetValue(item));
            }
            list.Add(expando as ExpandoObject);
        }
        return list;
    }
}

答案 1 :(得分:-1)

正如其他人所说,你应该最有可能使用强类型Persona类。它将使您的代码更易于阅读,使用和维护。

但是,如果必须使用dynamic,您可以做的一件事就是用包含所需信息的新项目替换要更改其属性的项目。

请注意,因为列表是dynamic,我们不知道它包含的对象的类型,这意味着盲目访问对象的属性很容易引发异常。

为了处理这个问题,您需要在访问它之前确保该属性存在。并且,在进行比较之前,我们还需要确保它是正确的类型。这会产生相当丑陋的代码,这只是在可能的情况下使用强类型类的另一个原因。

foreach (var item in ListaPersonas.ToList())
{
    if (item.GetType().GetProperty("Nombre") != null &&
        item.GetType().GetProperty("Nombre").PropertyType.Equals(typeof(string)) && 
        item.Nombre == "jose")
    {
        ListaPersonas.Remove(item);
        ListaPersonas.Add(new { valor = 7, Nombre = item.Nombre });
    }
}

答案 2 :(得分:-1)

问题

请考虑以下事项:

List<dynamic> ListaPersonas = new List<dynamic>() {        
    new { valor = 1, Name = "maria" }, //Has Name, no Nombre
    new { Bar = 2, Nombre="jose" }, //Has Bar, no valor
    new { valor = 3, Foo="juan", Bar = 1 } //has valor, no Nombre, and added Foo & Bar
}; 

这将编译得很好。现在应用您之前所做的相同逻辑:

foreach (var item in ListaPersonas)
{
    //This would throw an exception on dynamics that did not have a "Nombre" property
    if (item.Nombre == "jose") 
    {
        item.valor = 7;
    }            
}

这将抛出异常,因为并非所有动态对象都具有属性Nombre

建议

我强烈建议您创建一个描述数据的类:

public class Persona
{
    public string Nombre { get; set; }
    public int Valor { get; set; }   
}

然后您可以轻松执行以下操作:

List<Persona> ListaPersonas = new List<Persona>() {
    new Persona() { Valor = 1, Nombre="maria" },
    new Persona() { Valor = 2, Nombre="jose" },
    new Persona() { Valor = 3, Nombre="juan" }
}; 

foreach (var item in ListaPersonas)
    if (item.Nombre == "jose")
        item.Valor = 7;