简体   繁体   English

AutoMapper:将多个属性映射为一个

[英]AutoMapper: mapping many properties into one

The scenario is the following: I receive a message containing a lot of variables, several hundreds. 场景如下:我收到一条包含大量变量的消息,数百个。 I need to write this to Azure Table storage where the partition key is the name of the individual variables and the value gets mapped to eg Value. 我需要将此写入Azure Table存储,其中分区键是单个变量的名称,值将映射到例如Value。

Let's say the payload looks like the following: 假设有效载荷如下所示:

public class Payload
{
    public long DeviceId { get; set; }
    public string Name { get; set; }
    public double Foo { get; set; }
    public double Rpm { get; set; }
    public double Temp { get; set; }
    public string Status { get; set; }
    public DateTime Timestamp { get; set; }
}

And my TableEntry like this: 我的TableEntry是这样的:

public class Table : TableEntity
{
    public Table(string partitionKey, string rowKey)
    {
        this.PartitionKey = partitionKey;
        this.RowKey = rowKey;
    }

    public Table() {}
    public long DeviceId { get; set; }
    public string Name { get; set; }
    public double Value { get; set; }
    public string Signal { get; set; }
    public string Status { get; set; }
}

In order to write that to Table storage, I need to 为了将其写入Table存储,我需要

var table = new Table(primaryKey, payload.Timestamp.ToString(TimestampFormat))
{
    DeviceId = payload.DeviceId,
    Name = payload.Name,
    Status = payload.Status,
    Value = value (payload.Foo or payload.Rpm or payload.Temp),
    Signal = primarykey/Name of variable ("foo" or "rmp" or "temp"),
    Timestamp = payload.Timestamp
};
var insertOperation = TableOperation.Insert(table);
await this.cloudTable.ExecuteAsync(insertOperation);

I don't want to copy this 900 times (or how many variables there happen to be in the payload message; this is a fixed number). 我不想复制这900次(或者有效载荷消息中发生了多少变量;这是一个固定的数字)。

I could make a method to create the table, but I will still have to call this 900 times. 我可以创建一个方法来创建表,但我仍然需要调用900次。

I thought maybe AutoMapper could help out. 我想也许AutoMapper可以提供帮助。

Are they always the same variables? 它们总是相同的变量吗? A different approach could be to use DynamicTableEntity in which you basically have a TableEntity where you can fill out all additional fields after the RowKey/PartitionKey Duo: 一种不同的方法可能是使用DynamicTableEntity,其中你基本上有一个TableEntity,你可以在RowKey / PartitionKey Duo之后填写所有其他字段:

var tableEntity = new DynamicTableEntity();
tableEntity.PartitionKey = "partitionkey";
tableEntity.RowKey = "rowkey";

dynamic json = JsonConvert.DeserializeObject("{bunch:'of',stuff:'here'}");
foreach(var item in json)
{
    tableEntity.Properties.Add(item.displayName, item.value);
}
// Save etc

The problem is to map these properties, it is right? 问题是要映射这些属性,这是对的吗?

Value = value (payload.Foo or payload.Rpm or payload.Temp),
Signal = primarykey/Name of variable ("foo" or "rmp" or "temp"),

This conditional mapping can be done via Reflection: 这种条件映射可以通过Reflection完成:

object payload = new A { Id = 1 };
object value = TryGetPropertyValue(payload, "Id", "Name"); //returns 1

payload = new B { Name = "foo" };
value = TryGetPropertyValue(payload, "Id", "Name"); //returns "foo"

.

public object TryGetPropertyValue(object obj,  params string[] propertyNames)
{
    foreach (var name in propertyNames)
    {
        PropertyInfo propertyInfo = obj.GetType().GetProperty(name);

        if (propertyInfo != null) return propertyInfo.GetValue(obj);
    }

    throw new ArgumentException();
}

You may map rest of properties (which have equal names in source and destination) with AutoMapper.Mapper.DynamicMap call instead of AutoMapper.Mapper.Map to avoid creation of hundreds configuration maps. 您可以使用AutoMapper.Mapper.DynamicMap调用而不是AutoMapper.Mapper.Map来映射其余属性(在源和目标中具有相同名称),以避免创建数百个配置映射。 Or just cast your payload to dynamic and map it manually. 或者只是将payloaddynamic并手动映射。

You can create a DynamicTableEntity from your Payload objects with 1-2 lines of code using TableEntity.Flatten method in the SDK or use the ObjectFlattenerRecomposer Nuget package if you are also worried about ICollection type properties. 您可以使用SDK中的TableEntity.Flatten方法使用1-2行代码从Payload对象创建DynamicTableEntity,或者如果您还担心ICollection类型属性,则使用ObjectFlattenerRecomposer Nuget包。 Assign it PK/RK and write the flattened Payload object into the table as a DynamicTableEntity. 将其分配PK / RK并将展平的Payload对象作为DynamicTableEntity写入表中。 When you read it back, read it as DynamicTableEntity and you can use TableEntity.ConvertBack method to recreate the original object. 当您回读它时,将其读作DynamicTableEntity,您可以使用TableEntity.ConvertBack方法重新创建原始对象。 Dont even need that intermediate Table class. 甚至不需要那个中间表类。

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

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