在CRM Online中动态使用GetAttributeValue <t>

时间:2016-03-06 20:25:21

标签: c# plugins dynamics-crm

我运行C#代码来比较CRM中的前后图像,以确定某个字段是否发生了变化(长话短说:我无法控制的外部过程每次更新记录中的每个字段,即使字段也是如此没有改变)。我想使用CRM GetAttributeValue(attributeName)来执行此操作,但是当我可能不知道字段名称时,我想动态地执行它。所以,例如,我想这样做:

// pretend the value of firstname is not hard-coded but submitted on a form    
// (not really on a form, but just know it's not hard-coded like it is below.)
string fieldToCheck = "firstname"; 
if (preImage.GetAttributeValue<T>(fieldToCheck) != postImage.GetAttributeValue<T>(fieldToCheck))
{
  // do something here. I've tried something like the below, but it doesn't work with error "t is a variable but used like a type". 
  Type t = preImage.Attributes[fieldToCheck].GetType();
  var val = preImage.GetAttributeValue<t>(fieldToCheck);

}

我遇到的问题是<T>可能会有所不同,具体取决于fieldToCheck的值。在firstname的情况下,它将是<string>,在new_DateOpened的情况下,它将是<DateTime>,等等。我必须有脑痉挛,因为我应该能够弄清楚如何动态获取T的值,但不能。

2 个答案:

答案 0 :(得分:1)

泛型类型参数T不等于类型Type的实例。您可以使用T -> Type来使用类型参数typeof(T),但不能轻易地使用Type -> T。类型T必须在编译时正常知道。

你可以用这里的反射(How do I use reflection to call a generic method?)显然做到这一点:

MethodInfo method = typeof(Entity).GetMethod("GetAttributeValue");
MethodInfo generic = method.MakeGenericMethod(t);
generic.Invoke(preImage, fieldToCheck); // and postImage

答案 1 :(得分:1)

对于大多数(如果不是全部)属性类型,您可以依赖于常见的Equals(object o)方法。这也适用于基于类EntityReferenceOptionSetValueMoney的属性。

您只需要对null值进行额外检查。 (当属性在系统中具有null值时,它将不会出现在前映像或后映像的属性集合中。)

public static bool IsAttributeModified(string attributeName, Entity preImage, Entity postImage)
{
    object preValue;

    if (preImage.Attributes.TryGetValue(attributeName, out preValue))
    {
        object postValue;
        return !postImage.Attributes.TryGetValue(attributeName, out postValue) || !preValue.Equals(postValue);
    }

    return postImage.Attributes.ContainsKey(attributeName);
}