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

3

我正在运行一个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的值,但我可能脑抽了。

既然你正在使用 var,为什么不使用 GetType?来确定 fieldToCheck 中的数据类型呢? - Aizen
修改了代码。fieldToCheck将始终是一个字符串。它只是我想要获取的CRM属性的名称。 - Jeff
2个回答

1
对于大多数(如果不是全部)属性类型,您可以依靠常见的Equals(object o)方法。这也适用于基于类EntityReference、OptionSetValue和Money的属性。
您只需要对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);
}

1

一个泛型类型参数 T 不等于类型实例 Type。你可以通过使用 typeof(T) 从类型参数 T -> Type,但不能轻松地从 Type -> T 转换。通常编译时必须了解类型 T。

显然,您可以通过反射在此处(如何使用反射调用泛型方法?)实现这一点:

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

我支持这个答案,但出于某种原因,他在将类型推到var作为匿名类型。不知道为什么。 - Aizen
你的意思是他执行 var fieldToCheck = "firstname" 时?在那个实例中,var 并不意味着匿名类型,而是隐含了一个字符串类型。 - trousyt
是的,因为双引号的原因,但请检查他在顶部的注释。假装代码没有硬编码。 - Aizen
fieldToCheck将始终是一个字符串。它代表Microsoft CRM实体上属性的名称。但是,该名称表示的属性可能是任何类型:字符串、日期/时间、数字、CRM选项集等,这就是为什么我不知道类型会是什么。我选择这条路是因为我无法控制的外部过程会更新每个字段,即使值没有改变。这导致我的CRM工作流触发,因为电子邮件字段值已更改,而实际上并没有更改-因此我使用pre和post图像进行比较。 - Jeff
1
Jeff,如果可以的话,我会使用@Henk-van-Boeijen的答案。由于性能影响,我会尽可能避免使用反射。 - trousyt
那是我的倾向,但我对他的回答有一个后续问题。 - Jeff

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接