private PluginMethod CreateFrom(System.Reflection.MethodInfo method, string logicalname) { var result = new PluginMethod(); result.method = method; var parameters = method.GetParameters().ToArray(); result.Parameters = new TypeCache[parameters.Length]; var ix = 0; foreach (var parameter in parameters) { result.Parameters[ix] = TypeCache.ForParameter(parameter, logicalname); ix++; } var sortAttr = method.GetCustomAttributes(Types.SortAttribute, false).SingleOrDefault(); if (sortAttr != null) { result.Sort = (int)sortAttr.GetType().GetProperty("Value").GetValue(sortAttr); } else { result.Sort = 1; } return(result); }
public object Resolve(TypeCache type) { try { if (services.ContainsKey(type.ObjectInstanceKey)) { return(services[type.ObjectInstanceKey]); } if (type.IsTarget && !type.IsReference) { var entity = (Microsoft.Xrm.Sdk.Entity)pluginExecutionContext.InputParameters["Target"]; services[type.ObjectInstanceKey] = Extensions.Sdk.KiponSdkGeneratedExtensionMethods.ToEarlyBoundEntity(entity); return(services[type.ObjectInstanceKey]); } if (type.IsPreimage) { var imgName = PluginMethod.ImageSuffixFor(1, pluginExecutionContext.Stage, pluginExecutionContext.Mode == 1); var entity = (Microsoft.Xrm.Sdk.Entity)pluginExecutionContext.PreEntityImages[imgName]; services[type.ObjectInstanceKey] = Extensions.Sdk.KiponSdkGeneratedExtensionMethods.ToEarlyBoundEntity(entity); return(services[type.ObjectInstanceKey]); } if (type.IsPostimage) { var imgName = PluginMethod.ImageSuffixFor(2, pluginExecutionContext.Stage, pluginExecutionContext.Mode == 1); var entity = (Microsoft.Xrm.Sdk.Entity)pluginExecutionContext.PostEntityImages[$"postimage{imgName}"]; services[type.ObjectInstanceKey] = Extensions.Sdk.KiponSdkGeneratedExtensionMethods.ToEarlyBoundEntity(entity); return(services[type.ObjectInstanceKey]); } if (type.IsMergedimage) { var target = (Microsoft.Xrm.Sdk.Entity)pluginExecutionContext.InputParameters["Target"]; var merged = new Microsoft.Xrm.Sdk.Entity(); merged.Id = target.Id; merged.LogicalName = target.LogicalName; var imgName = PluginMethod.ImageSuffixFor(1, pluginExecutionContext.Stage, pluginExecutionContext.Mode == 1); var pre = (Microsoft.Xrm.Sdk.Entity)pluginExecutionContext.PreEntityImages[imgName]; foreach (var attr in pre.Attributes.Keys) { merged[attr] = pre[attr]; } foreach (var attr in target.Attributes.Keys) { merged[attr] = target[attr]; } services[type.ObjectInstanceKey] = Extensions.Sdk.KiponSdkGeneratedExtensionMethods.ToEarlyBoundEntity(merged); return(services[type.ObjectInstanceKey]); } if (type.IsReference) { var target = (Microsoft.Xrm.Sdk.EntityReference)pluginExecutionContext.InputParameters["Target"]; if (type.Constructor != null) { services[type.ObjectInstanceKey] = type.Constructor.Invoke(new object[] { target }); } else { services[type.ObjectInstanceKey] = target; } return(services[type.ObjectInstanceKey]); } if (type.FromType == typeof(Microsoft.Xrm.Sdk.IOrganizationService)) { return(this.GetOrganizationService(type.RequireAdminService)); } if (type.IsQuery) { var uow = this.GetIUnitOfWork(type.RequireAdminService); var queryProperty = type.RepositoryProperty; var repository = queryProperty.GetValue(uow, new object[0]); var queryMethod = type.QueryMethod; return(queryMethod.Invoke(repository, new object[0])); } if (type.FromType == typeof(Guid)) { if (type.Name.ToLower() == "id") { return(pluginExecutionContext.PrimaryEntityId); } if (type.Name.ToLower() == "listid") { return(pluginExecutionContext.InputParameters["ListId"]); } if (type.Name.ToLower() == "entityid") { return(pluginExecutionContext.InputParameters["EntityId"]); } throw new Exceptions.UnresolveableParameterException(type.FromType, type.Name); } return(this.CreateServiceInstance(type)); } catch (System.Collections.Generic.KeyNotFoundException) { var typeName = (type?.FromType?.FullName) ?? "type was null"; var key = type?.ObjectInstanceKey ?? "object instance key as null"; throw new InvalidPluginExecutionException($"Unable to resolve service {typeName}, {key} or one of its dependencies."); } }
private void AddIfConsistent(Type type, System.Reflection.MethodInfo method, List <PluginMethod> results, PluginMethod result, string message, int stage) { #region validate pre and post image consistancy switch (stage) { case 10: case 20: /* pre image pre event */ if (result.HasPreimageThatIsNotMergedImage() && message == "Create") { throw new Exceptions.UnavailableImageException(type, method, "Preimage", stage, message); } /* post image pre event */ if (result.HasPostimage()) { throw new Exceptions.UnavailableImageException(type, method, "Postimage", stage, message); } break; case 40: case 41: if (result.HasPostimage() && message == "Delete") { throw new Exceptions.UnavailableImageException(type, method, "Postimage", stage, message); } break; } #endregion #region validate target consistancy if (result.HasTargetBesideReference() && message == "Delete") { throw new Exceptions.UnavailableImageException(type, method, "Target", stage, message); } if (result.HasTargetReference()) { var inError = true; if (message == "Delete") { // delete always provides an entity reference as target, everything is good inError = false; } var mess = message.Split('_'); if (mess.Length >= 2) { // this looks a lot like a custom action, it has the pattern prefix_name, bounded actions will also provide an entity reference, so we are good inError = false; } // ADD other conditions where target is relevant, ex associate if (inError) { throw new Exceptions.UnavailableImageException(type, method, "Target", stage, message); } } #endregion results.Add(result); if (result.method.ReturnType != null) { var outputProperties = result.method.ReturnType.GetProperties(System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance); if (outputProperties != null && outputProperties.Length > 0) { var output = new Dictionary <System.Reflection.PropertyInfo, Output>(); foreach (var p in outputProperties) { var outputAttr = p.GetCustomAttribute(Types.OutputAttribute); if (outputAttr != null) { var name = (string)outputAttr.GetType().GetProperty("LogicalName").GetValue(outputAttr); var req = (bool)outputAttr.GetType().GetProperty("Required").GetValue(outputAttr); output.Add(p, new Output { LogicalName = name, Requred = req }); } } if (output.Count > 0) { result.OutputProperties = output; } } } }
public object Resolve(TypeCache type, Microsoft.Xrm.Sdk.IOrganizationService orgService) { try { if (services.ContainsKey(type.ObjectInstanceKey)) { return(services[type.ObjectInstanceKey]); } lock (locks) { if (services.ContainsKey(type.ObjectInstanceKey)) { return(services[type.ObjectInstanceKey]); } if (type.FromType == typeof(Guid) && type.Name != null && type.Name.ToLower() == nameof(this.pluginExecutionContext.PrimaryEntityId).ToLower()) { return(this.pluginExecutionContext.PrimaryEntityId); } if (type.FromType == typeof(string) && type.Name != null && type.Name.ToLower() == nameof(this.pluginExecutionContext.PrimaryEntityName).ToLower()) { return(this.pluginExecutionContext.PrimaryEntityName); } if (type.FromType == typeof(string) && type.Name != null && type.Name.ToLower() == nameof(BasePlugin.UnsecureConfig).ToLower()) { return(this.UnsecureConfig); } if (type.FromType == typeof(string) && type.Name != null && type.Name.ToLower() == nameof(BasePlugin.SecureConfig).ToLower()) { return(this.SecureConfig); } if (type.FromType == typeof(Microsoft.Xrm.Sdk.Query.QueryExpression)) { if (pluginExecutionContext.InputParameters.Contains("Query")) { var query = pluginExecutionContext.InputParameters["Query"]; if (query is Microsoft.Xrm.Sdk.Query.QueryExpression qe) { // no cache by design - need to be resolved on all request. return(qe); } if (query is Microsoft.Xrm.Sdk.Query.FetchExpression fe) { var resp = (Microsoft.Crm.Sdk.Messages.FetchXmlToQueryExpressionResponse)orgService.Execute(new Microsoft.Crm.Sdk.Messages.FetchXmlToQueryExpressionRequest { FetchXml = fe.Query }); return(resp.Query); } throw new Exceptions.UnresolvedQueryParameter(type.Name); } else { throw new InvalidPluginExecutionException("QueryExpression can only be requested for RetrieveMultiple requests"); } } if (type.IsTarget && !type.IsReference) { var entity = (Microsoft.Xrm.Sdk.Entity)pluginExecutionContext.InputParameters["Target"]; services[type.ObjectInstanceKey] = Extensions.Sdk.KiponSdkGeneratedExtensionMethods.ToEarlyBoundEntity(entity); return(services[type.ObjectInstanceKey]); } if (type.IsPreimage) { var imgName = PluginMethod.ImageSuffixFor(1, pluginExecutionContext.Stage, pluginExecutionContext.Mode == 1); var entity = (Microsoft.Xrm.Sdk.Entity)pluginExecutionContext.PreEntityImages[imgName]; services[type.ObjectInstanceKey] = Extensions.Sdk.KiponSdkGeneratedExtensionMethods.ToEarlyBoundEntity(entity); return(services[type.ObjectInstanceKey]); } if (type.IsPostimage) { var imgName = PluginMethod.ImageSuffixFor(2, pluginExecutionContext.Stage, pluginExecutionContext.Mode == 1); var entity = (Microsoft.Xrm.Sdk.Entity)pluginExecutionContext.PostEntityImages[$"postimage{imgName}"]; services[type.ObjectInstanceKey] = Extensions.Sdk.KiponSdkGeneratedExtensionMethods.ToEarlyBoundEntity(entity); return(services[type.ObjectInstanceKey]); } if (type.IsMergedimage) { var merged = new Microsoft.Xrm.Sdk.Entity(); var target = pluginExecutionContext.InputParameters["Target"] as Microsoft.Xrm.Sdk.Entity; if (target != null) { merged.Id = target.Id; merged.LogicalName = target.LogicalName; } else { var er = pluginExecutionContext.InputParameters["Target"] as Microsoft.Xrm.Sdk.EntityReference; merged.Id = er.Id; merged.LogicalName = er.LogicalName; } if (pluginExecutionContext.MessageName == "Create") { merged = target; } else { var imgName = PluginMethod.ImageSuffixFor(1, pluginExecutionContext.Stage, pluginExecutionContext.Mode == 1); var pre = (Microsoft.Xrm.Sdk.Entity)pluginExecutionContext.PreEntityImages[imgName]; foreach (var attr in pre.Attributes.Keys) { merged[attr] = pre[attr]; } if (target != null) { foreach (var attr in target.Attributes.Keys) { merged[attr] = target[attr]; } } } services[type.ObjectInstanceKey] = Extensions.Sdk.KiponSdkGeneratedExtensionMethods.ToEarlyBoundEntity(merged); return(services[type.ObjectInstanceKey]); } if (type.IsReference) { var target = (Microsoft.Xrm.Sdk.EntityReference)pluginExecutionContext.InputParameters["Target"]; if (type.Constructor != null) { services[type.ObjectInstanceKey] = type.Constructor.Invoke(new object[] { target }); } else { services[type.ObjectInstanceKey] = target; } return(services[type.ObjectInstanceKey]); } if (type.FromType == typeof(Microsoft.Xrm.Sdk.IOrganizationService)) { return(this.GetOrganizationService(type.RequireAdminService)); } if (type.IsQuery) { var uow = this.GetIUnitOfWork(type.RequireAdminService); var repositoryProperty = type.RepositoryProperty; var repository = repositoryProperty.GetValue(uow, new object[0]); var queryMethod = type.QueryMethod; return(queryMethod.Invoke(repository, new object[0])); } if (type.IsRepository) { var uow = this.GetIUnitOfWork(type.RequireAdminService); var queryProperty = type.RepositoryProperty; return(queryProperty.GetValue(uow, new object[0])); } if (type.IsEntityCache) { var uow = this.GetIUnitOfWork(type.RequireAdminService); var cacheProperty = uow.GetType().GetProperty("Cache"); return(cacheProperty.GetValue(uow, new object[0])); } if (type.FromType == typeof(Guid)) { if (type.Name.ToLower() == "id") { return(pluginExecutionContext.PrimaryEntityId); } if (type.Name.ToLower() == "listid") { return(pluginExecutionContext.InputParameters["ListId"]); } if (type.Name.ToLower() == "entityid") { return(pluginExecutionContext.InputParameters["EntityId"]); } throw new Exceptions.UnresolveableParameterException(type.FromType, type.Name); } if (type.FromType == typeof(Microsoft.Xrm.Sdk.Relationship)) { if (pluginExecutionContext.InputParameters.Contains("Relationship")) { return((Microsoft.Xrm.Sdk.Relationship)pluginExecutionContext.InputParameters["Relationship"]); } throw new InvalidPluginExecutionException("Relationship is requested as input parameter but there is no such information in the payload"); } return(this.CreateServiceInstance(type)); } } catch (System.Collections.Generic.KeyNotFoundException) { var typeName = (type?.FromType?.FullName) ?? "type was null"; var key = type?.ObjectInstanceKey ?? "object instance key as null"; throw new InvalidPluginExecutionException($"Unable to resolve service {typeName}, {key} or one of its dependencies."); } }
private void AddIfConsistent(Type type, System.Reflection.MethodInfo method, List <PluginMethod> results, PluginMethod result, string message, int stage) { #region validate pre and post image consistancy switch (stage) { case 10: case 20: /* pre image pre event */ if (result.HasPreimage() && message == "Create") { throw new Exceptions.UnavailableImageException(type, method, "Preimage", stage, message); } /* post image pre event */ if (result.HasPostimage()) { throw new Exceptions.UnavailableImageException(type, method, "Postimage", stage, message); } break; case 40: case 41: if (result.HasPostimage() && message == "Delete") { throw new Exceptions.UnavailableImageException(type, method, "Postimage", stage, message); } break; } #endregion #region validate target consistancy if (result.HasTargetBesideReference() && message == "Delete") { throw new Exceptions.UnavailableImageException(type, method, "Target", stage, message); } if (result.HasTargetReference()) { var inError = true; if (message == "Delete") { inError = false; } // ADD other conditions where target is relevant, ex associate if (inError) { throw new Exceptions.UnavailableImageException(type, method, "Target", stage, message); } } #endregion results.Add(result); }