Reputation: 621
I have C# code running to compare pre and post-images in CRM to determine if a field changed (long story short: external process I can't control is updating every field on a record every time, even if fields haven't changed). I want to use the CRM GetAttributeValue(attributeName) to do it, but I want to do it dynamically when I may not know the field name. So, for example, I want to do this:
// 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);
}
The problem I'm having is that <T>
could be different depending on the value of fieldToCheck
. In the case of firstname it would be <string>
, in the case of new_DateOpened it would be <DateTime>
, etc. I must be having a brain spasm because I should be able to figure out how to dynamically get the value of T, but can't.
Upvotes: 3
Views: 1807
Reputation: 7938
For most (if not all) attribute types you can rely on the common Equals(object o)
method. This also works for the attributes based on classes EntityReference
, OptionSetValue
and Money
.
You only need to do an extra check on null
values. (When an attribute has a null
value in the system it will not be present in the attribute collection of a pre- or post-image.)
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);
}
Upvotes: 1
Reputation: 356
A generic type parameter T
is not equal to an instance of type Type
. You can go from type param T -> Type
using typeof(T)
, but not from Type -> T
easily. Type T must be known at compile time normally.
You CAN apparently do this with reflection per here (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
Upvotes: 1