繁体   English   中英

C# - 如何遍历 object 的每个属性和值

[英]C# - how to loop through each property & value of an object

我在 C# 中有以下DTO C#

public class Customer
{
   public int Id { get; set;}

   public string Name { get;set;}

   // & so on (say 25 properties)
}

我使用DynmoDb作为 Db(NoSql),将上述项目添加到 DynamoDb 表中。 这就是我的方法的样子

 public async Task<bool> Add(Customer customer)
    {
        try
        {
            var res = await _dynamoClient.PutItemAsync(
            tableName: _tableName, item: SetObject(customer)).ConfigureAwait(false);
            return res.HttpStatusCode == System.Net.HttpStatusCode.OK
        }
        catch (Exception ex)
        {
            Logger.Log(ex, eventObj);
            return false;
        }
    }

私有 SetObject() 方法:-

private Dictionary<string, AttributeValue> SetObject(Customer obj)
    {
        //DynamoDb - Using Low Level API
        var attributes = new Dictionary<string,
        AttributeValue> {
            //Id
            {
                nameof(obj.Id),
                new AttributeValue {
                    S = obj.Id
                }
            },
            //Name
            {
                nameof(obj.Name),
                new AttributeValue {
                    S = obj.Name.Trim()
                }
            },
        };
        return attributes;
    }

这种私有方法对我来说看起来很麻烦且容易出错。 我不想以这种方式逐个查找每个属性。

我在想是否有某种方法可以遍历所有属性并将namevalue分配给Dictionary集合

 var propsList = typeof(EventTO).GetProperties().Select(x => x.Name).ToList<string>();

这给了我所有的属性名称,但是我如何从传递的 object 类型的客户中获取值和键。

谢谢!

您可以使用反射,像这样,也可以使用 Generics 以获得更好的类型安全性

using System;
using System.Reflection;

class TestClass
{
    public int publicIntField;
    public string publicStringField;
    public int publicIntProp {get; set;}
    public string publicStringProp {get; set;}
    public static int staticInt;
}

public class Program
{
    public static void Main()
    {
        var src = new TestClass();
        src.publicIntField = 7;
        src.publicIntProp = 12;
        src.publicStringField = "foo";
        src.publicStringProp = "baz";

        var dest = new TestClass();
        DoIt(src, dest);
        TestClass dest1 = DoItWithGenerics(src);
    }

    public static void  DoIt(object src, object dest)
    {
        Console.WriteLine("DoIt");
        Type t = src.GetType();
        // TODO  check the 2 objects have same type

        foreach (PropertyInfo  p in t.GetProperties(BindingFlags.Public|BindingFlags.Instance))
        {
            Console.WriteLine(p.Name);
            p.SetValue(dest, p.GetValue(src));
        }

        foreach (FieldInfo  fi in t.GetFields(BindingFlags.Public|BindingFlags.Instance))
        {
            Console.WriteLine(fi.Name);
            fi.SetValue(dest, fi.GetValue(src));
        }
        Console.WriteLine("*****");
    }

    public static T DoItWithGenerics<T>(T src) where T:new() // only works for types with a default ctor
    {
        Console.WriteLine("DoItWithGenerics");

        Type t = typeof(T);
        T dest = new T();

        foreach (PropertyInfo  p in t.GetProperties(BindingFlags.Public|BindingFlags.Instance))
        {
            Console.WriteLine(p.Name);
            p.SetValue(dest, p.GetValue(src));
        }

        foreach (FieldInfo  fi in t.GetFields(BindingFlags.Public|BindingFlags.Instance))
        {
            Console.WriteLine(fi.Name);
            fi.SetValue(dest, fi.GetValue(src));
        }
        Console.WriteLine("*****");
        return dest;
    }
}

在这个小提琴中看到

这是一种克隆每种类型的 object 的方法

它需要一些修改来处理您正在使用的“Trim()”部分。

你最好使用像https://github.com/ServiceStack/PocoDynamo这样的库

这完成了所有映射工作,为您转换为所需的发电机请求,因此您不必担心。

对于 Javascript,AWS 有 documentClient 库,可以让任务更轻松。 对于 .net,我们使用上述库。

//Configuration for client
var awsDb = new AmazonDynamoDBClient("keyId","key",
new AmazonDynamoDBConfig { ServiceURL="http://localhost:8000"});
var db = new PocoDynamo(awsDb);

//Create c# dto
var itemToSave = new Item();
itemToSave.Id = 1;
itemToSave.Name = "Test";

//Single line to save it
db.PutItem(itemToSave);

看看这个: https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/reflection 它可能会帮助您简化项目、减少冗余并提高性能,并返回变量的值。 我自己还没有使用它,但我的同事是它的忠实粉丝。

我不确定它会在多大程度上帮助你,我不能让我的同事检查这个,因为他正在度假

使用更多反射!

因此,您拥有类型上每个属性的所有名称。 现在您需要一个该类型的实例来获取属性的值。 您可以这样做:

// Assume that 'event' is an instance of EventTO
foreach (var propertyName in propsList)
{
    object value = event.GetType().GetProperty(propertyName).GetValue(event, null);
    // Do whatever with 'value'
}

如您所见,我们有一些冗余代码(GetType 和 GetProperty),因此我们可以将 PropertyInfo 存储在 a 中并像这样使用它,而不是将我们的属性作为其名称的字符串存储在列表中:

var propsList = typeof(EventTO).GetProperties();
foreach (var property in propsList)
{
    object value = property.GetValue(event, null);
}

提示: PropertyInfo有一个名为PropertyType的属性,它返回属性的类型

我会使用 FastMember 之类的库来遍历 object 中的属性并将其转换为AttributeValue字典(请参阅: https://github.com/mgravell/fast-member

与像 FastMember 这样的优化库相比,反射通常非常慢。

 public class Dto
{
    public string Name { get; set; }
    public string Address { get; set; }
}

static void Convert()
{
    var dto = new Dto { Name = "Name", Address = "Address" };

    var ta = TypeAccessor.Create(typeof(Dto));
    var oa = ObjectAccessor.Create(dto);
    var values = new Dictionary<string, AttributeValue>();

    foreach (var m in ta.GetMembers())
    {
        values.Add(m.Name, new AttributeValue { S = oa[m.Name].ToString() });
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM