【问题标题】:Dynamically set properties of a Dynamic object动态设置 Dynamic 对象的属性
【发布时间】:2019-05-03 07:18:00
【问题描述】:

我有一个动态对象,它基本上包含一个 AvroRecord。 AvroRecord 课程详情here.

我可以静态地为属性赋值,但我想知道这是否可以动态地完成。我查看了论坛问题hereherehere。但这些都不适合我。

这是有效的静态代码。

    var serializer = AvroSerializer.CreateGeneric(Schema);
    var rootSchema = serializer.WriterSchema as RecordSchema;
    dynamic counterpartRow = new AvroRecord(rootSchema);
    counterpartRow.CounterpartID = Row.CounterpartID
    counterpartRow.CounterpartFirstDepositDate = Row.CounterpartFirstDepositDate

Row 是 SSIS 的 InputBuffer 类的一个对象,它包含来自上游数据源的所有列。

上面使用的 schema 变量是一个 avro schema,大概是这样的。

 Schema = @"{
                                ""type"":""record"",
                                ""name"":""Microsoft.Hadoop.Avro.Specifications.Counterparts"",
                                ""fields"":
                                    [
                                       { ""name"":""CounterpartID"", ""type"":""int"" },
                                       { ""name"":""CounterpartFirstDepositDate"",  ""type"":[""string"",""null""] },
                                       { ""name"":""CounterpartFirstTradeDate"",""type"":[""string"",""null""] },
                                       { ""name"":""ClientSegmentReportingID"",""type"":""int"" },
                                       { ""name"":""ClientSegmentReportingName"", ""type"":[""string"",""null""] },
                                       { ""name"":""ContractID"", ""type"":""int""},
                                       { ""name"":""ContractFirstDepositDate"", ""type"":[""string"",""null""]},
                                       { ""name"":""ContractFirstTradeDate"",""type"":[""string"",""null""] },
                                       { ""name"":""ContractClosingOffice"",""type"":[""string"",""null""] },
                                       { ""name"":""LeadCreationDate"", ""type"":[""string"",""null""] },
                                       { ""name"":""ContractCountryOfResidence"", ""type"":[""string"",""null""]}
                                    ]
                            }";

我尝试过类似早期论坛链接的建议,如

counterpartRow.GetType().GetField("CounterpartID").SetValue(Row, Row.CounterpartID, null);

还有另一种方法(显然应该适用于动态类型),但即使这样也不行。

foreach (string propertyName in GetPropertyKeysForDynamic(counterpartRow.Schema.Fields()))
        {
            string propertyValue = counterpartRow[propertyName];


        }

和这样定义的函数。

 public List<string> GetPropertyKeysForDynamic(dynamic dynamicToGetPropertiesFor)
    {
        var jObject = (JObject)JToken.FromObject(dynamicToGetPropertiesFor);
        Dictionary<string, object> values = jObject.ToObject<Dictionary<string, object>>();
        List<string> toReturn = new List<string>();
        foreach (string key in values.Keys)
        {
            toReturn.Add(key);
        }
        return toReturn;
    }

上面的字典返回空白。

上面提到的Row是InputBuffer类(SSIS中自动生成的类)的一个对象。

是这样的。

public class Input0Buffer: ScriptBuffer

{
    public Input0Buffer(PipelineBuffer Buffer, int[] BufferColumnIndexes, OutputNameMap OutputMap)
        : base(Buffer, BufferColumnIndexes, OutputMap)
    {
    }

    public Int32 CounterpartID
    {
        get
        {
            return Buffer.GetInt32(BufferColumnIndexes[0]);
        }
    }
------more properties

如果您看到我的原始静态代码,我正在尝试动态生成分配。我已经动态生成了模式(而不是我上面给出的静态定义)。所以,唯一剩下要动态生成的就是assignment的assignment了。一个想法可能是我生成字符串,但我如何执行该字符串?只有在没有办法实现这一点的情况下。

【问题讨论】:

  • Dynamic 只是一个在运行时接受任何类型的关键字。您实际上并没有动态对象,而是 AvroRecord 类型。你得看看这个类型是怎么操作的。
  • 感谢您的回复。是的,我知道,但也许这个问题的标题框架不是最合适的。无论如何,我希望我提供的第三个链接有效:*.com/questions/2634858/…。但事实并非如此。 AvroRecord 扩展 DynamicObject 和 DynamicObject 实现 IDynamicMetaObjectProvider。无论如何,我将阅读有关 DynamicObject 类(AvroRecord 扩展)的更多信息。

标签: c# reflection ssis


【解决方案1】:

如果我理解正确你的问题,我认为你可以尝试这样的事情

        string _schema = "your avro schema"
        RecordSchema _record = (RecordSchema)Avro.Schema.Parse(_schema);
        GenericRecord _generic_record = new GenericRecord(payload_record);
        for (int ii = 0; ii < _record.Fields.Count; ii++)
        {
            _generic_record.Add(_record.Fields[ii].Name, Raw.TheFiledYouNeed);
        }

【讨论】: