Reputation: 7555
I have below DTO
class in C#
public class Customer
{
public int Id { get; set;}
public string Name { get;set;}
// & so on (say 25 properties)
}
I am using DynmoDb
as Db(NoSql), to add the above item to DynamoDb table. This is how my method looks like
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;
}
}
Private SetObject() method:-
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;
}
This private method looks cumbersome & error prone to me. I don't want to look up through each property one by one in this way.
I am thinking if there is some way to loop through all the properties & assign name
& value
to Dictionary
collection
var propsList = typeof(EventTO).GetProperties().Select(x => x.Name).ToList<string>();
This gives me all the property names but how do I fetch the value & key from the passed object of type customer.
Thanks!
Upvotes: 2
Views: 13133
Reputation: 4249
You can use reflection, with something like this, also with Generics for better type safety
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;
}
}
See at work in this fiddle
This is a way to Clone every type of object
It requires some modification to handle the "Trim()" part you are using.
Upvotes: 2
Reputation: 952
You would be better off using a library like https://github.com/ServiceStack/PocoDynamo
This does all the mapping job, of converting to the required dynamo request for you, so you don't have to worry about it.
For Javascript, AWS has documentClient library which makes the task easier. For .net we use the above library.
//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);
Upvotes: 2
Reputation: 8116
I'd use a library like FastMember to iterate over properties in an object and convert it to an AttributeValue
dictionary (See: https://github.com/mgravell/fast-member)
Reflection is in general quite slow compared to an optimized library like 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() });
}
}
Upvotes: 1
Reputation: 7855
Using more Reflection!
So you have all the names of every property on a Type. Now you need an instance of that type to get the Values of the properties on. Here is how you can do that:
// 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'
}
As you can see we have some redundant code (GetType and GetProperty), so instead of storing our properties as a string of their names in a list, we can store the PropertyInfo in a and use it like so:
var propsList = typeof(EventTO).GetProperties();
foreach (var property in propsList)
{
object value = property.GetValue(event, null);
}
Hint: PropertyInfo has a Property called PropertyType
which returns the Type of the property
Upvotes: 2
Reputation: 122
Check this out: https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/reflection. It might help you to simplify your project, reduce redundancy and increase performance, as well as return you the value of the variable. I haven't used it myself yet but my coworker is a big fan of it.
I'm not sure up to which extend it will help you tho and i can't ask my coworker to check on this one since he is on vacation
Upvotes: 2