FrameworkTemplate/Common/Plugins/ImageHelpers.cs
using System; using Microsoft.Xrm.Sdk; namespace Common { public static class ImageHelpers { public const string PreEntityImageName = "PreImage"; public const string PostEntityImageName = "PostImage"; /// <summary> /// This utility method can be used to find the final attribute of an entity in a given time. /// If the attribute is being updated it will retrieve the updating version of the attribute, otherwise it will use the value of the pre-image /// </summary> internal static object GetFinalAttribute(this IExecutionContext context, string attributeName, string preEntityImageName) { bool gettingSet; return context.GetFinalAttribute(attributeName, preEntityImageName, out gettingSet); } internal static object GetFinalAttribute(this IExecutionContext context, string attributeName, string preEntityImageName, out bool gettingSet) { object contextAtt = context.GetContextAttribute(attributeName, out gettingSet); if (gettingSet) { return contextAtt; } return context.GetOriginalAttribute(attributeName, preEntityImageName); } internal static object GetContextAttribute(this IExecutionContext context, string attributeName, out bool gettingSet) { // Use gettingSet boolean because if the value is getting set to null there is no other way to tell whether // the attribute is not getting set (not in the context) or whether it is getting set to null explicitly. gettingSet = false; if (context.InputParameters.ContainsKey("Target")) { var newVersion = context.InputParameters["Target"] as Entity; if (newVersion != null && newVersion.Contains(attributeName)) { // The attribute is being updated, use the new value gettingSet = true; return newVersion[attributeName]; } } else if (attributeName.Equals("statecode", StringComparison.InvariantCultureIgnoreCase) && context.InputParameters.Contains("State")) { gettingSet = true; return context.InputParameters["State"]; } else if (attributeName.Equals("statuscode", StringComparison.InvariantCultureIgnoreCase) && context.InputParameters.Contains("Status")) { gettingSet = true; return context.InputParameters["Status"]; } return null; } internal static object GetOriginalAttribute(this IExecutionContext context, string attributeName, string preEntityImageName) { if (context.PreEntityImages.Contains(preEntityImageName)) { var oldVersion = context.PreEntityImages[preEntityImageName]; if (oldVersion.Contains(attributeName)) { // Return the attribute value from the PreImage return oldVersion[attributeName]; } } return null; } internal static object GetPostImageAttribute(this IExecutionContext context, string attributeName, string postEntityImageName) { if (context.PostEntityImages.Contains(postEntityImageName)) { var newVersion = context.PostEntityImages[postEntityImageName]; if (newVersion.Contains(attributeName)) { // Return the attribute value from the PostImage return newVersion[attributeName]; } } return null; } internal static bool IsEntityReferenceImageEqual(EntityReference e1, EntityReference e2) { if (e1 == null && e2 == null) { return true; } if (e1 == null || e2 == null) { return false; } return e1.Id == e2.Id; } internal static bool IsOptionSetImageEqual(OptionSetValue o1, OptionSetValue o2) { if (o1 == null && o2 == null) { return true; } if (o1 == null || o2 == null) { return false; } return o1.Value == o2.Value; } internal static bool IsAttributeImageEqual<T>(this IExecutionContext context, string attributeName, string preEntityImageName) { var preValue = context.GetOriginalAttribute(attributeName, preEntityImageName); var finalValue = context.GetFinalAttribute(attributeName, preEntityImageName); if (typeof(T) == typeof(OptionSetValue)) return IsOptionSetImageEqual((OptionSetValue)preValue, (OptionSetValue)finalValue); if (typeof(T) == typeof(EntityReference)) return IsEntityReferenceImageEqual((EntityReference)preValue, (EntityReference)finalValue); return preValue == finalValue; } internal static bool IsStringImageEqual(string s1, string s2) { // In CRM pipeline null is treated as string.Empty sometimes, so treat these equally. // For example, when setting string field to null, the plugin will actually catch "" value in the attributes if (s1 == null && s2 == null) { return true; } if (s1 == null && s2 == string.Empty) { return true; } if (s1 == string.Empty && s2 == null) { return true; } return s1 == s2; } internal static bool IsValueDifferent(object attributeValue, object originalValue) { if (attributeValue == null) { if (originalValue == null) { return false; } return true; } var stringNewValue = attributeValue as string; if (stringNewValue != null) { var stringOldValue = originalValue as string; return !IsStringImageEqual(stringOldValue, stringNewValue); } var osvNewValue = attributeValue as OptionSetValue; if (osvNewValue != null) { var osvOldValue = originalValue as OptionSetValue; return !IsOptionSetImageEqual(osvOldValue, osvNewValue); } var erNewValue = attributeValue as EntityReference; if (erNewValue != null) { var erOldValue = originalValue as EntityReference; return !IsEntityReferenceImageEqual(erOldValue, erNewValue); } var iNewValue = attributeValue as int?; if (iNewValue != null) { var iOldValue = originalValue as int?; return iOldValue != iNewValue; } var bNewValue = attributeValue as bool?; if (bNewValue != null) { var bOldValue = originalValue as bool?; return bOldValue != bNewValue; } return true; // Other datatypes not covered, assume value is different } public static TEntity GetPreImage<TEntity>(this IExecutionContext context, string preEntityImageName = PreEntityImageName) where TEntity : Entity { TEntity preImage = null; if (context.PreEntityImages.Contains(preEntityImageName)) { preImage = context.PreEntityImages[preEntityImageName].ToEntity<TEntity>(); } return preImage; } public static TEntity GetPostImage<TEntity>(this IExecutionContext context, string postEntityImageName = PostEntityImageName) where TEntity : Entity { TEntity postImage = null; if (context.PostEntityImages.Contains(postEntityImageName)) { postImage = context.PostEntityImages[postEntityImageName].ToEntity<TEntity>(); } return postImage; } } } |