private void ExecutePipelineStage(string method, ProcessingStepStage stage, ProcessingStepMode mode, EntityReference entityReference)
        {
            var entityType = FindReflectedType(entityReference.LogicalName);

            if (entityType == null)
            {
                return;
            }

            var plugins = GetStepsForStage(method, stage, mode, (Entity)Activator.CreateInstance(entityType));

            ExecutePipelinePlugins(plugins, entityReference);
        }
        /// <summary>
        /// Registers the <typeparamref name="TPlugin"/> as a SDK Message Processing Step.
        /// </summary>
        /// <typeparam name="TPlugin">The plugin to register the step for.</typeparam>
        /// <param name="message">The message that should trigger the execution of plugin.</param>
        /// <param name="stage">The stage when the plugin should be executed.</param>
        /// <param name="mode">The mode in which the plugin should be executed.</param>
        /// <param name="rank">The order in which this plugin should be executed in comparison to other plugins registered with the same <paramref name="message"/> and <paramref name="stage"/>.</param>
        /// <param name="filteringAttributes">When not one of these attributes is present in the execution context, the execution of the plugin is prevented.</param>
        /// <param name="primaryEntityTypeCode">The entity type code to filter this step for.</param>
        public void RegisterPluginStep <TPlugin>(string message, ProcessingStepStage stage = ProcessingStepStage.Postoperation, ProcessingStepMode mode = ProcessingStepMode.Synchronous, int rank = 1, string[] filteringAttributes = null, int?primaryEntityTypeCode = null)
            where TPlugin : IPlugin
        {
            // Message
            var sdkMessage = this.CreateQuery("sdkmessage").FirstOrDefault(sm => string.Equals(sm.GetAttributeValue <string>("name"), message));

            if (sdkMessage == null)
            {
                sdkMessage = new Entity("sdkmessage")
                {
                    Id       = Guid.NewGuid(),
                    ["name"] = message
                };
                this.AddEntityWithDefaults(sdkMessage);
            }

            // Plugin Type
            var type         = typeof(TPlugin);
            var assemblyName = type.Assembly.GetName();

            var pluginType = this.CreateQuery("plugintype").FirstOrDefault(pt => string.Equals(pt.GetAttributeValue <string>("typename"), type.FullName) && string.Equals(pt.GetAttributeValue <string>("asemblyname"), assemblyName.Name));

            if (pluginType == null)
            {
                pluginType = new Entity("plugintype")
                {
                    Id               = Guid.NewGuid(),
                    ["name"]         = type.FullName,
                    ["typename"]     = type.FullName,
                    ["assemblyname"] = assemblyName.Name,
                    ["major"]        = assemblyName.Version.Major,
                    ["minor"]        = assemblyName.Version.Minor,
                    ["version"]      = assemblyName.Version.ToString(),
                };
                this.AddEntityWithDefaults(pluginType);
            }

            // Filter
            Entity sdkFilter = null;

            if (primaryEntityTypeCode.HasValue)
            {
                sdkFilter = new Entity("sdkmessagefilter")
                {
                    Id = Guid.NewGuid(),
                    ["primaryobjecttypecode"] = primaryEntityTypeCode
                };
                this.AddEntityWithDefaults(sdkFilter);
            }

            // Message Step
            var sdkMessageProcessingStep = new Entity("sdkmessageprocessingstep")
            {
                Id = Guid.NewGuid(),
                ["eventhandler"]        = pluginType.ToEntityReference(),
                ["sdkmessageid"]        = sdkMessage.ToEntityReference(),
                ["sdkmessagefilterid"]  = sdkFilter?.ToEntityReference(),
                ["filteringattributes"] = filteringAttributes != null?string.Join(",", filteringAttributes) : null,
                                              ["mode"]  = new OptionSetValue((int)mode),
                                              ["stage"] = new OptionSetValue((int)stage),
                                              ["rank"]  = rank
            };

            this.AddEntityWithDefaults(sdkMessageProcessingStep);
        }
        /// <summary>
        /// Registers the <typeparamref name="TPlugin"/> as a SDK Message Processing Step for the Entity <typeparamref name="TEntity"/>.
        /// </summary>
        /// <typeparam name="TPlugin">The plugin to register the step for.</typeparam>
        /// <typeparam name="TEntity">The entity to filter this step for.</typeparam>
        /// <param name="message">The message that should trigger the execution of plugin.</param>
        /// <param name="stage">The stage when the plugin should be executed.</param>
        /// <param name="mode">The mode in which the plugin should be executed.</param>
        /// <param name="rank">The order in which this plugin should be executed in comparison to other plugins registered with the same <paramref name="message"/> and <paramref name="stage"/>.</param>
        /// <param name="filteringAttributes">When not one of these attributes is present in the execution context, the execution of the plugin is prevented.</param>
        public void RegisterPluginStep <TPlugin, TEntity>(string message, ProcessingStepStage stage = ProcessingStepStage.Postoperation, ProcessingStepMode mode = ProcessingStepMode.Synchronous, int rank = 1, string[] filteringAttributes = null)
            where TPlugin : IPlugin
            where TEntity : Entity, new()
        {
            var entity         = new TEntity();
            var entityTypeCode = (int)entity.GetType().GetField("EntityTypeCode").GetValue(entity);

            RegisterPluginStep <TPlugin>(message, stage, mode, rank, filteringAttributes, entityTypeCode);
        }
        private IEnumerable <Entity> GetStepsForStage(string method, ProcessingStepStage stage, ProcessingStepMode mode, Entity entity)
        {
            var query = new QueryExpression("sdkmessageprocessingstep")
            {
                ColumnSet = new ColumnSet("configuration", "filteringattributes", "stage", "mode"),
                Criteria  =
                {
                    Conditions =
                    {
                        new ConditionExpression("stage", ConditionOperator.Equal, (int)stage),
                        new ConditionExpression("mode",  ConditionOperator.Equal, (int)mode)
                    }
                },
                Orders =
                {
                    new OrderExpression("rank", OrderType.Ascending)
                },
                LinkEntities =
                {
                    new LinkEntity("sdkmessageprocessingstep",  "sdkmessagefilter",      "sdkmessagefilterid", "sdkmessagefilterid", JoinOperator.LeftOuter)
                    {
                        EntityAlias = "sdkmessagefilter",
                        Columns     = new ColumnSet("primaryobjecttypecode")
                    },
                    new LinkEntity("sdkmessageprocessingstep",  "sdkmessage",            "sdkmessageid",       "sdkmessageid", JoinOperator.Inner)
                    {
                        EntityAlias  = "sdkmessage",
                        Columns      = new ColumnSet("name"),
                        LinkCriteria =
                        {
                            Conditions =
                            {
                                new ConditionExpression("name", ConditionOperator.Equal, method)
                            }
                        }
                    },
                    new LinkEntity("sdkmessageprocessingstep",  "plugintype",            "eventhandler",       "plugintypeid", JoinOperator.Inner)
                    {
                        EntityAlias = "plugintype",
                        Columns     = new ColumnSet("assemblyname", "typename")
                    }
                }
            };

            var entityTypeCode = (int?)entity.GetType().GetField("EntityTypeCode")?.GetValue(entity);

            var plugins = this.Service.RetrieveMultiple(query).Entities.AsEnumerable();

            plugins = plugins.Where(p =>
            {
                var primaryObjectTypeCode = p.GetAttributeValue <AliasedValue>("sdkmessagefilter.primaryobjecttypecode");

                return(primaryObjectTypeCode == null || entityTypeCode.HasValue && (int)primaryObjectTypeCode.Value == entityTypeCode.Value);
            });

            // Todo: Filter on attributes

            return(plugins);
        }
        private void ExecutePipelineStage(string method, ProcessingStepStage stage, ProcessingStepMode mode, Entity entity)
        {
            var plugins = GetStepsForStage(method, stage, mode, entity);

            ExecutePipelinePlugins(plugins, entity);
        }
Exemplo n.º 6
0
        private IEnumerable <Entity> GetStepsForStage(string method, ProcessingStepStage stage, ProcessingStepMode mode, Entity entity)
        {
            var query = new QueryExpression("sdkmessageprocessingstep")
            {
                ColumnSet = new ColumnSet("configuration", "filteringattributes", "stage", "mode"),
                Criteria  =
                {
                    Conditions =
                    {
                        new ConditionExpression("stage", ConditionOperator.Equal, (int)stage),
                        new ConditionExpression("mode",  ConditionOperator.Equal, (int)mode)
                    }
                },
                Orders =
                {
                    new OrderExpression("rank", OrderType.Ascending)
                },
                LinkEntities =
                {
                    new LinkEntity("sdkmessageprocessingstep",  "sdkmessagefilter",      "sdkmessagefilterid", "sdkmessagefilterid", JoinOperator.LeftOuter)
                    {
                        EntityAlias = "sdkmessagefilter",
                        Columns     = new ColumnSet("primaryobjecttypecode")
                    },
                    new LinkEntity("sdkmessageprocessingstep",  "sdkmessage",            "sdkmessageid",       "sdkmessageid", JoinOperator.Inner)
                    {
                        EntityAlias  = "sdkmessage",
                        Columns      = new ColumnSet("name"),
                        LinkCriteria =
                        {
                            Conditions =
                            {
                                new ConditionExpression("name", ConditionOperator.Equal, method)
                            }
                        }
                    },
                    new LinkEntity("sdkmessageprocessingstep",  "plugintype",            "eventhandler",       "plugintypeid", JoinOperator.Inner)
                    {
                        EntityAlias = "plugintype",
                        Columns     = new ColumnSet("assemblyname", "typename")
                    }
                }
            };

            var entityTypeCode = (int?)entity.GetType().GetField("EntityTypeCode")?.GetValue(entity);

            if (!entityTypeCode.HasValue)
            {
                var response = (RetrieveEntityResponse)this.Service.Execute(new RetrieveEntityRequest {
                    LogicalName = entity.LogicalName, EntityFilters = EntityFilters.Entity
                });
                entityTypeCode = response.EntityMetadata.ObjectTypeCode;
            }

            var plugins = this.Service.RetrieveMultiple(query).Entities.AsEnumerable();

            plugins = plugins.Where(p =>
            {
                var primaryObjectTypeCode = p.GetAttributeValue <AliasedValue>("sdkmessagefilter.primaryobjecttypecode");

                bool consider = primaryObjectTypeCode == null || entityTypeCode.HasValue && (int)primaryObjectTypeCode.Value == entityTypeCode.Value;
                if (!consider)
                {
                    return(false);
                }

                var filteringAttributes = p.GetAttributeValue <string>("filteringattributes");
                if (method == "Update" && filteringAttributes != null && !string.IsNullOrEmpty(filteringAttributes.Trim()))
                {
                    var parts = filteringAttributes.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries).Select(e => e.Trim()).ToList();
                    return(parts.Any(filter => entity.Attributes.ContainsKey(filter)));
                }

                return(true);
            });

            return(plugins);
        }