public static void SetupAssemblyPlugins( this CrmPluginAssembly pluginAssembly, Assembly assembly, IReadOnlyCollection <XElement> unsecureConfigItems, IEnumerable <SdkMessage> messages, IEnumerable <SdkMessageFilter> messageFilters) { Version sdkVersion = null; var types = assembly .GetExportedTypes() .Where( t => !t.IsAbstract && t.IsClass && (t.Name.EndsWith("Plugin") || t.Name.EndsWith("Activity"))); foreach (var t in types) { CrmPluginType type; CrmPluginIsolatable isolatable; var xrmPlugin = t.GetInterface(typeof(IPlugin).FullName); if (xrmPlugin != null) { type = CrmPluginType.Plugin; isolatable = CrmPluginIsolatable.Yes; if (sdkVersion == null) { sdkVersion = xrmPlugin.Assembly.GetName().Version; pluginAssembly.SdkVersion = new Version(xrmPlugin.Assembly.GetName().Version.Major, xrmPlugin.Assembly.GetName().Version.Minor); } pluginAssembly.SdkVersion = new Version(sdkVersion.Major, sdkVersion.Minor); } else if (t.IsSubclassOf(typeof(Activity))) { type = CrmPluginType.WorkflowActivity; isolatable = CrmPluginIsolatable.No; } else { throw new Exception("Class is not plugin or workflow"); } var plugin = new CrmPlugin { TypeName = t.FullName, PluginType = type, AssemblyId = pluginAssembly.AssemblyId, AssemblyName = pluginAssembly.Name, Isolatable = isolatable, FriendlyName = Guid.NewGuid().ToString() }; if (type == CrmPluginType.WorkflowActivity) { var attr = t.GetCustomAttribute <WorkflowActivityAttribute>(); plugin.WorkflowActivityGroupName = " " + attr.WorkflowActivityGroupName; plugin.Name = " " + attr.Name; } var pluginEntityType = t.BaseType?.GetGenericArguments().LastOrDefault(); if (pluginEntityType == null) { // note: be sure - it is workflow:) pluginAssembly.AddPlugin(plugin); continue; } var splitted = t.FullName?.Split('.').Reverse().Take(2).ToArray(); var typeName = splitted?[0].Replace("Plugin", string.Empty); plugin.Name = $" {splitted?[1]}: {typeName}"; var stepMethods = t.GetMethods(BindingFlags.Public | BindingFlags.Instance).Where(m => m.DeclaringType == t).ToArray(); foreach (var stepMethod in stepMethods) { var pluginStepAttrs = stepMethod.GetCustomAttributes <PluginStepAttribute>(); var filteringAttributes = stepMethod.GetCustomAttribute <FilteringAttributesAttribute>(); foreach (var pluginStepAttr in pluginStepAttrs) { var step = new CrmPluginStep { AssemblyId = plugin.AssemblyId, PluginId = plugin.Id, DeleteAsyncOperationIfSuccessful = pluginStepAttr.DeleteAsyncOperationIfSuccessful, Deployment = CrmPluginStepDeployment.ServerOnly, Enabled = pluginStepAttr.Enabled, Name = RegistrationHelper.GenerateStepName(typeName, pluginStepAttr.PluginMessageName, pluginStepAttr.EntityLogicalName.ToLowerInvariant(), null), Rank = pluginStepAttr.Rank, Stage = (CrmPluginStepStage)pluginStepAttr.Stage, Mode = pluginStepAttr.ExecutionMode == PluginExecutionMode.Asynchronous ? CrmPluginStepMode.Asynchronous : CrmPluginStepMode.Synchronous, MessageId = messages.First(m => m.Name == pluginStepAttr.PluginMessageName).Id }; var filter = messageFilters.FirstOrDefault( f => f.SdkMessageId.Id == step.MessageId && f.PrimaryEntityLogicalName == pluginStepAttr.EntityLogicalName.ToLowerInvariant()); if (filter == null) { throw new Exception($"{pluginStepAttr.EntityLogicalName} entity doesn't registered yet"); } step.MessageEntityId = filter.Id; if (filteringAttributes != null) { step.FilteringAttributes = filteringAttributes.ToString(); } var unsecureItem = unsecureConfigItems.FirstOrDefault(it => it.Attribute("key").Value == pluginStepAttr.UnsecureConfig); if (unsecureItem != null) { var value = unsecureItem.Attribute("value").Value; step.UnsecureConfiguration = value == $"#{{{pluginStepAttr.UnsecureConfig}}}" ? unsecureItem.Attribute("default").Value : value; } foreach (var p in stepMethod.GetParameters().Where(p => p.ParameterType == pluginEntityType)) { var imageParameters = p.GetCustomAttribute <ImageParametersAttribute>(); if (imageParameters == null) { continue; } CrmPluginImage image; switch (p.Name) { case "preEntityImage": image = CreateImage(step, imageParameters.ToString(), pluginStepAttr.PluginMessageName, CrmPluginImageType.PreImage); step.AddImage(image); break; case "postEntityImage": image = CreateImage(step, imageParameters.ToString(), pluginStepAttr.PluginMessageName, CrmPluginImageType.PostImage); step.AddImage(image); break; } } plugin.AddStep(step); } } pluginAssembly.AddPlugin(plugin); } }