Dynamics crm + 如何在插件代码中根据类型动态获取属性值

Dynamics crm + how to get attribute value based on the type dynamically in plugin code

我有以下要求。

我需要对同一实体的多个记录中的每个字段执行总和但是在执行总和时,我还需要检查类型并相应地转换它们。例如,将整数转换为 Int,将 Decimal 转换为十进制。还有一些值也是别名值。我正在寻找一个通用函数,我可以为别名字段和直接字段调用它,它将 return 我根据类型

得到值

下面写代码的背景-

字段值存储在AttributeList中的格式-

AttributeList = { "price ",  "quantity", "contact.revenue", "opportunity.sales"}

下面是我到目前为止尝试过的代码 -

我的属性列表中只有小数和整数字段。

private void calculate(List<string> attributeList,List<Entity> mainEntityList,Guid targetId,Guid oppId,Guid contactId)
{

    var mainentity = new mainEntity();
    mainentity.Id = targetId;

    var opportunity = new Opportunity();
    opportunity.Id = oppId;

    var contact = new Contact();
    contact.Id = contactId;


    foreach (var attribute in attributeList)
    {

        var fieldSum = new decimal(0);
        int intFieldSum = 0;
        bool attributeFound = false;

        foreach (var entity in mainEntityList)
        {
            
            if (entity.Contains(attribute))
            {
                var type = entity[attribute].GetType().Name;
                attributeFound = true;

                switch (type)
                    {
                        case "AliasedValue":
                        var aliasedFieldValue = entity.GetAttributeValue<AliasedValue>(attribute);
                        if (aliasedFieldValue.Value.GetType().Name == "Decimal")
                        {
                        decimalFieldSum += (decimal)aliasedFieldValue.Value;
                        }
                        else
                        {
                        intFieldSum += (int)aliasedFieldValue.Value;
                        }
                        break;
                        case "Decimal":
                        decimalFieldSum += entity.GetAttributeValue<decimal>(attribute);
                        break;
                        case "Int32":
                        intFieldSum += entity.GetAttributeValue<int>(attribute);
                        break;
                        default:
                            break;
                    }
            }
        }

        if (attributeFound)
        {
            if (attribute.Contains("opportunity"))
            {
                opportunity[attribute] =  decimalFieldSum != 0 ? decimalFieldSum : intFieldSum; 
            }
            else if (attribute.Contains("contact"))
            {
                contact[attribute] = decimalFieldSum != 0 ? decimalFieldSum : intFieldSum; 
            }
            else
            {
                mainentity[attribute] = decimalFieldSum != 0 ? decimalFieldSum : intFieldSum; 
            }
        }
    }

    service.update(opportunity);
    service.update(contact);
    service.update(mainentity);
}

如有任何帮助,我们将不胜感激。

只是稍微编辑了您的代码。

...

var fieldSum = new decimal(0);
foreach (var entity in mainEntityList)
{
    fieldSum += GetAttrValue(entity, attribute);
}

...

您可以使用此函数计算小数类型的fieldSum变量。

private decimal GetAttrValue(Entity entity, string attribute)
{
    var attrValue = new decimal(0);
    
    if (!entity.Contains(attribute) || entity.Attributes[attribute] == null)
    {
        return attrValue;
    }
    
    var type = entity.Attributes[attribute].GetType().Name;
    switch (type)
    {
        case "AliasedValue":
            var aliasedFieldValue = entity.GetAttributeValue<AliasedValue>(attribute);
            attrValue = type == "Decimal" ? (decimal)aliasedFieldValue.Value : (int)aliasedFieldValue.Value;
            break;
        case "Decimal":
            attrValue = entity.GetAttributeValue<decimal>(attribute);
            break;
        case "Int32":
            attrValue = entity.GetAttributeValue<int>(attribute);
            break;
        default:
            break;
    }
    return attrValue;
}

另一方面,如果您只需要一个通用函数,它将 return 十进制或 int 值作为属性,您可以使用此

private T GetAttrValue<T>(Entity entity, string attribute)
{
    if (!entity.Contains(attribute) || entity.Attributes[attribute] == null)
    {
        return default(T);
    }

    T result;
    var type = entity.Attributes[attribute].GetType().Name;
    if (type == "AliasedValue")
    {
        var aliasedFieldValue = entity.GetAttributeValue<AliasedValue>(attribute);
        result = (T)aliasedFieldValue.Value;
    }
    else
    {
        result = entity.GetAttributeValue<T>(attribute);
    }
    return result;
}

--更新--
所以,如果我理解你的要求的话,这里是完整的代码。
首先添加这个 class.

public class AttributeInfo
{
    public string Name { get; set; }

    public Type Type { get; set; }

    public decimal DecimalSum { get; set; } = new decimal(0);

    public int IntSum { get; set; } = 0;
}

并添加此功能

private void SetValue(Entity entity, AttributeInfo attributeInfo)
{
    if (entity.Contains(attributeInfo.Name))
    {
        switch (attributeInfo.Type.Name)
        {
            case "Decimal":
                entity[attributeInfo.Name] = attributeInfo.DecimalSum;
                break;
            case "Int32":
                entity[attributeInfo.Name] = attributeInfo.IntSum;
                break;
            default:
                break;
        }
    }
}

那么这就是你的Calculate功能

private void Calculate(List<string> attributeList, List<Entity> mainEntityList, Guid targetId, Guid oppId, Guid contactId)
{
    var mainentity = new mainEntity();
    mainentity.Id = targetId;

    var opportunity = new Opportunity();
    opportunity.Id = oppId;

    var contact = new Contact();
    contact.Id = contactId;

    var attributesInfo = new List<AttributeInfo>();
    foreach (var attribute in attributeList)
    {
        var attributeInfo = new AttributeInfo
        {
            Name = attribute
        };

        foreach (var entity in mainEntityList)
        {
            if (entity.Contains(attribute))
            {
                attributeInfo.Type = entity[attribute].GetType();
                switch (attributeInfo.Type.Name)
                {
                    case "AliasedValue":
                        var aliasedFieldValue = entity.GetAttributeValue<AliasedValue>(attribute);
                        if (aliasedFieldValue.Value.GetType().Name == "Decimal")
                        {
                            attributeInfo.DecimalSum += (decimal)aliasedFieldValue.Value;
                        }
                        else
                        {
                            attributeInfo.IntSum += (int)aliasedFieldValue.Value;
                        }
                        break;
                    case "Decimal":
                        attributeInfo.DecimalSum += entity.GetAttributeValue<decimal>(attribute);
                        break;
                    case "Int32":
                        attributeInfo.IntSum += entity.GetAttributeValue<int>(attribute);
                        break;
                    default:
                        break;
                }
            }
        }

        attributesInfo.Add(attributeInfo);
    }

    foreach (var attributeInfo in attributesInfo)
    {
        if (attributeInfo.Type != null)
        {
            SetValue(mainentity, attributeInfo);
            SetValue(opportunity, attributeInfo);
            SetValue(contact, attributeInfo);
        }
    }

    service.update(mainentity);
    service.update(opportunity);
    service.update(contact);
}

我应该说 calculate 函数的结构对我来说仍然很奇怪。不过,这里我尽量保留主体结构。