我运行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的值,但不能。
答案 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)
方法。这也适用于基于类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);
}