C # - как пройти через каждое свойство и значение объекта - PullRequest
1 голос
/ 27 сентября 2019

У меня ниже 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;
    }

Этот закрытый метод выглядит громоздким и подверженным ошибкам.Я не хочу просматривать каждое свойство по одному таким образом.

Я думаю, есть ли какой-нибудь способ перебрать все свойства и назначить name & value для Dictionary collection

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

Это дает мне все имена свойств, но как мне получить значение и ключ из переданного объекта типа customer.

Спасибо!

Ответы [ 5 ]

2 голосов
/ 27 сентября 2019

Вам лучше использовать такую ​​библиотеку, как 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);
2 голосов
/ 27 сентября 2019

Вы можете использовать отражение с чем-то вроде этого, также с 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;
    }
}

См. На работе в этой скрипке

Этоспособ клонирования каждого типа объекта

Требуется некоторая модификация для обработки используемой вами части "Trim ()".

1 голос
/ 27 сентября 2019

Используя больше 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 в и используйте его следующим образом:

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

Подсказка: PropertyInfo имеет свойство с именем PropertyType, которое возвращает тип свойства

1 голос
/ 27 сентября 2019

Проверьте это: https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/reflection. Это может помочь вам упростить ваш проект, уменьшить избыточность и повысить производительность, а также вернуть вам значение переменной.Я сам еще не использовал его, но мой коллега является его большим поклонником.

Я не уверен, до какой степени это поможет вам, и я не могу попросить моего коллегу проверить этоодин, так как он в отпуске

0 голосов
/ 27 сентября 2019

Я бы использовал библиотеку, подобную FastMember, для итерации по свойствам объекта и преобразования ее в словарь 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() });
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...