コード例 #1
0
ファイル: Rule.cs プロジェクト: cognitoforms/ExoRule
        /// <summary>
        /// Invokes the rule on the specified <see cref="ModelInstance"/> as a result
        /// of the specified triggering <see cref="ModelEvent"/>
        /// </summary>
        /// <param name="root"></param>
        /// <param name="modelEvent"></param>
        internal void Invoke(ModelInstance root, ModelEvent modelEvent)
        {
            try
            {
                if (BeforeInvoke != null)
                {
                    BeforeInvoke(this, EventArgs.Empty);
                }

                ModelEventScope.Perform(() => OnInvoke(root, modelEvent));
            }
            finally
            {
                if (AfterInvoke != null)
                {
                    AfterInvoke(this, EventArgs.Empty);
                }
            }
        }
コード例 #2
0
        /// <summary>
        /// Generates a script tag to embed a model including instance data into a server-rendered view.
        /// Supports initial customization of the model via an initialization delegate.
        /// </summary>
        /// <param name="query"></param>
        /// <param name="init"></param>
        /// <returns></returns>
        static void Model(TextWriter writer, object query, Delegate init)
        {
            // Raise the begin model event
            if (BeginModel != null)
            {
                BeginModel(query, EventArgs.Empty);
            }

            // Get the roots for each query
            var roots = new List <KeyValuePair <string, ServiceRequest.Query> >();

            foreach (var prop in query.GetType().GetProperties())
            {
                // Get the value of the model property
                var m = prop.GetValue(query, null);
                if (m == null)
                {
                    continue;
                }

                // Convert the value into a query, if necessary
                var q = m as ServiceRequest.Query ?? Query(m);
                if (q != null)
                {
                    q.LoadRoots(null);
                    roots.Add(new KeyValuePair <string, ServiceRequest.Query>(prop.Name, q));
                }
            }

            // Create the request object
            ServiceRequest request = new ServiceRequest(roots.Select(r => r.Value).ToArray());

            // Synthesize init new changes for new query roots
            ModelTransaction initChanges = (ModelTransaction)request.Queries
                                           .SelectMany(q => q.Roots)
                                           .Where(i => i.IsNew)
                                           .Select(i => new ModelInitEvent.InitNew(i))
                                           .Cast <ModelEvent>()
                                           .ToList();

            // Perform the initialization action, if specified
            if (init != null)
            {
                // Determine matching parameters
                var parameters = new object[init.Method.GetParameters().Length];
                foreach (var p in init.Method.GetParameters())
                {
                    foreach (var root in roots)
                    {
                        if (p.Name.Equals(root.Key, StringComparison.InvariantCultureIgnoreCase))
                        {
                            // List parameter
                            if (p.ParameterType.IsArray)
                            {
                                parameters[p.Position] = root.Value.Roots.Select(r => r.Instance).ToArray();
                            }

                            // Instance parameter
                            else
                            {
                                parameters[p.Position] = root.Value.Roots.Select(r => r.Instance).FirstOrDefault();
                            }

                            break;
                        }
                    }

                    // Throw an exception if the model property value cannot be cast to the corresponding initialization parameter
                    if (parameters[p.Position] != null && !p.ParameterType.IsAssignableFrom(parameters[p.Position].GetType()))
                    {
                        throw new ArgumentException(String.Format("The model property '{0}' cannot be converted into the initialization parameter type of '{1}'.", p.Name, p.ParameterType.FullName));
                    }

                    // Throw an exception if a valid model parameter could not be found to pass to the initialization delegate
                    if (parameters[p.Position] == null && query.GetType().GetProperty(p.Name, BindingFlags.Public | BindingFlags.IgnoreCase | BindingFlags.Instance) == null)
                    {
                        throw new ArgumentException(String.Format("A model property could not be found to pass to the initialization parameter '{0}'.", p.Name));
                    }
                }

                // Perform initialization while capturing changes
                initChanges.Record(() =>
                {
                    // Prevent property change rules from running until after initialization
                    ModelEventScope.Perform(() => init.DynamicInvoke(parameters));
                });
            }

            // Invoke the request queries
            ServiceResponse response = request.Invoke(initChanges);

            response.Model = roots.ToDictionary(r => r.Key, r => r.Value);
            foreach (var q in response.Model.Values)
            {
                q.ReducePaths();
            }

            // Track the current model roots to support server template rendering
            foreach (var root in response.Model)
            {
                Templates.Page.Current.Model[root.Key] = root.Value.IsList ? (object)root.Value.Roots : (root.Value.Roots.Length == 1 ?root.Value.Roots[0] : null);
            }

            // Write the model embed script to the writer
            writer.Write("<script type=\"text/javascript\">$exoweb(");
            JsonUtility.Serialize(writer, response);
            writer.Write(");</script>");

            // Raise the end model event
            if (EndModel != null)
            {
                EndModel(query, EventArgs.Empty);
            }
        }