コード例 #1
0
        /// <summary>
        /// Creates a method plan from the parameters listed.
        /// </summary>
        /// <param name="methodElement">An XML node where the method and parameters are found.</param>
        bool ExecuteMethod(XElement methodElement)
        {
            // Indicates the success or failure of an individual method execution.
            bool isSuccessful = false;

            try
            {
                // The client channel on which this method is to be executed is described by the 'client' attribute.
                XAttribute    clientAttribte = methodElement.Attribute("client");
                String        clientName     = clientAttribte == null ? String.Empty : clientAttribte.Value;
                ClientChannel client;
                if (!this.clientTable.TryGetValue(clientName, out client))
                {
                    throw new Exception(String.Format("The client {0} hasn't been defined", clientName == String.Empty ? "<default>" : clientName));
                }

                // Reflection is used here to find the method to be executed.
                XAttribute methodNameAttribute = methodElement.Attribute("name");
                String     methodName          = methodNameAttribute == null ? String.Empty : methodNameAttribute.Value;
                MethodInfo methodInfo          = client.ChannelType.GetMethod(methodNameAttribute.Value);
                if (methodInfo == null)
                {
                    throw new Exception(String.Format("The method {0} isn't part of the library", methodNameAttribute.Value));
                }

                // This will pull apart the XML that contains the parameters and construct a dictionary of method arguments.
                Dictionary <String, XElement> parameterDictionary = new Dictionary <String, XElement>();
                foreach (XElement parameterElement in methodElement.Elements("parameter"))
                {
                    XAttribute parameterNameAttribute = parameterElement.Attribute("name");
                    parameterDictionary.Add(parameterNameAttribute.Value, parameterElement);
                }

                // This will correlate the parameter in the XML with the parameter of the actual method found through reflection and convert the parameter into the
                // proper destination type.  The end result is a parameter array that is compatible with a reflection call to the method specified in the XML.
                ParameterInfo[] parameterInfoArray = methodInfo.GetParameters();
                Object[]        parameterArray     = new Object[parameterInfoArray.Length];
                for (int index = 0; index < parameterInfoArray.Length; index++)
                {
                    ParameterInfo parameterInfo = parameterInfoArray[index];
                    XElement      parameterElement;
                    if (parameterDictionary.TryGetValue(parameterInfo.Name, out parameterElement))
                    {
                        parameterArray[index] = ScriptLoader.ConvertElement(parameterInfo.ParameterType, parameterElement, Path.GetDirectoryName(this.FileName));
                    }
                }

                try
                {
                    // At this point, the only thing left to do is call the method using the parsed parameters.
                    methodInfo.Invoke(client.ChannelObject, parameterArray);
                }
                catch (TargetInvocationException targetInvocationException)
                {
                    // We use reflection to execute the method, so naturally we're going to get a reflection error.  This will dig out the real reason that this
                    // method failed and throw it.
                    throw targetInvocationException.InnerException;
                }

                // The method invocation was successful at this point.
                isSuccessful = true;
            }
            catch (FaultException <IndexNotFoundFault> indexNotFoundException)
            {
                // The record wasn't found.
                Console.WriteLine(Teraque.Properties.Resources.IndexNotFoundError, indexNotFoundException.Detail.IndexName,
                                  indexNotFoundException.Detail.TableName);
            }
            catch (FaultException <RecordNotFoundFault> recordNotFoundException)
            {
                // The record wasn't found.
                Console.WriteLine(Teraque.Properties.Resources.RecordNotFoundError,
                                  CommonConversion.FromArray(recordNotFoundException.Detail.Key),
                                  recordNotFoundException.Detail.TableName);
            }
            catch (FaultException <ConstraintFault> constraintFaultException)
            {
                // The arguments weren't in the proper range.
                Console.WriteLine(constraintFaultException.Detail.Message);
            }
            catch (FaultException <ArgumentFault> argumentFaultException)
            {
                // The arguments weren't in the proper range.
                Console.WriteLine(argumentFaultException.Detail.Message);
            }
            catch (FaultException <FormatFault> formatFaultException)
            {
                // The arguments weren't in the proper range.
                Console.WriteLine(formatFaultException.Detail.Message);
            }
            catch (FaultException <ExceptionDetail> exceptionDetail)
            {
                // This is a general purpose exception for debugging.
                Console.WriteLine(exceptionDetail.Message);
            }

            // This is the final indication of whether the method was successful or not.
            return(isSuccessful);
        }
コード例 #2
0
        static Int32 Main(String[] args)
        {
            // This object is used to load the script and keeps track of loading statistics.
            ScriptLoader scriptLoader = new ScriptLoader();

            // The endpoint is pulled from the application settings first.  It can be overridden with the command line.
            scriptLoader.Endpoint = Properties.Settings.Default.DataModelEndpoint;

            // These are the parameters that are parsed out of the command line.
            Boolean   forceLogin    = false;
            String    inputFilePath = String.Empty;
            Verbosity verbosity     = Verbosity.Minimal;

            try
            {
                // The command line parser is driven by different states that are triggered by the flags read.  Unless a flag has been parsed, the command line
                // parser assumes that it's reading the file name from the command line.
                ArgumentState argumentState = ArgumentState.InputFileName;

                // Parse the command line for arguments.
                foreach (String argument in args)
                {
                    // Use the dictionary to transition from one state to the next based on the input parameters.
                    ArgumentState nextArgumentState;
                    if (Program.argumentStates.TryGetValue(argument, out nextArgumentState))
                    {
                        argumentState = nextArgumentState;
                    }

                    // The parsing state will determine which variable is read next.
                    switch (argumentState)
                    {
                    case ArgumentState.EndpointParam:

                        // The next command line argument will be endpoint.
                        argumentState = ArgumentState.Endpoint;
                        break;

                    case ArgumentState.Endpoint:

                        // This will set the endpoint to use when communicating with the service.
                        scriptLoader.Endpoint = argument;
                        break;

                    case ArgumentState.ForceLoginParam:

                        // This will cause the script loader to prompt for login credentials.
                        forceLogin    = true;
                        argumentState = ArgumentState.InputFileName;
                        break;

                    case ArgumentState.InputFileParam:

                        // The next command line argument will be the input file name.
                        argumentState = ArgumentState.InputFileName;
                        break;

                    case ArgumentState.InputFileName:

                        // Expand the environment variables so that paths don't need to be absolute.
                        inputFilePath = Environment.ExpandEnvironmentVariables(argument);
                        break;

                    case ArgumentState.VerbosityParam:

                        // Verbose output.
                        argumentState = ArgumentState.Verbosity;
                        break;

                    case ArgumentState.Verbosity:

                        try
                        {
                            // Make sure any parsing errors are ignored.
                            verbosity = (Verbosity)Enum.Parse(typeof(Verbosity), argument);
                        }
                        catch { }

                        break;

                    default:

                        // The parser will revert back to looking for an input file when it doesn't recognized the switch.
                        argumentState = ArgumentState.InputFileName;
                        break;
                    }
                }

                // Throw a usage message back at the user if no file name was given.
                if (inputFilePath == null)
                {
                    throw new Exception("Usage: \"Script Loader\" [-b <Batch Size>] [-f] -i <FileName>");
                }

                // Expand the environment variables and load the resulting file.
                scriptLoader.ForceLogin = forceLogin;
                scriptLoader.FileName   = inputFilePath;
                scriptLoader.Verbosity  = verbosity;
                scriptLoader.Load();
            }
            catch (Exception exception)
            {
                // Dump the error.
                Console.WriteLine(exception.Message);

                // This will force an abnormal exit from the program.
                scriptLoader.HasErrors = true;
            }

            // Print the final status of the load.
            Console.WriteLine(String.Format("{0} {1}: {2} Methods Executed", DateTime.Now.ToString("u"), scriptLoader.ScriptName, scriptLoader.MethodCount));

            // If an error happened anywhere, don't exit normally.
            if (scriptLoader.HasErrors)
            {
                return(1);
            }

            // After a successful load, the properties (specifically user name and password) can be saved for the next invocation of this application.
            Properties.Settings.Default.Save();

            // If we reached here, the file was imported without issue.
            return(0);
        }
コード例 #3
0
        /// <summary>
        /// Converts an XElement describing a value to a native CLR value.
        /// </summary>
        /// <param name="type">The target datatype.</param>
        /// <param name="parameterElement">An XElement containing a String representation of a value.</param>
        /// <param name="directoryName">The directory where external files can be found.</param>
        /// <returns>The native CLR value of the described value.</returns>
        static Object ConvertElement(Type type, XElement parameterElement, String directoryName)
        {
            // If the target parameter is an array, then construct a vector parameter.
            if (type == typeof(Object[]))
            {
                // The values can be found in a single attribute of the 'parameter' element or be listed as children.  This list collects both methods of describing
                // values and constructs a single array when all elements and attributes are parsed.
                List <Object> valueList = new List <Object>();

                // An attribute can be used to desribe a value.  An optional 'Type' attribute can specify what type of conversion is used to evaluate the CLR value.
                XAttribute valueAttribute = parameterElement.Attribute("value");
                if (valueAttribute != null)
                {
                    valueList.Add(ScriptLoader.ConvertValue(ScriptLoader.GetElementType(typeof(String), parameterElement), valueAttribute.Value));
                }

                // It is possible to specify the value using the content of an XML element or through an "import" statement.  This will cycle through any nodes of
                // the parameter looking for additional nodes containing the data for the parameter.
                foreach (XObject xObject in parameterElement.Nodes())
                {
                    // This uses the element content as the value for the parameter.
                    if (xObject is XText)
                    {
                        XText xText = xObject as XText;
                        valueList.Add(ConvertValue(typeof(String), xText.Value));
                    }

                    // Elements can be nested inside the parameter element to greater detail to the parameter.
                    if (xObject is XElement)
                    {
                        // This element holds special instructions for the parameter.
                        XElement xElement = xObject as XElement;

                        // Values for a key can be specified as child elements of the parameter.
                        if (xElement.Name == "value")
                        {
                            valueList.Add(ConvertValue(GetElementType(typeof(String), xElement), xElement.Value));
                        }

                        // This special instruction allows the value of a parameter to come from an external file.  This is used primary to load XML content into a
                        // record.
                        if (xElement.Name == "import")
                        {
                            XAttribute xAttribute = xElement.Attribute("path");
                            String     path       = Path.IsPathRooted(xAttribute.Value) ? xAttribute.Value : Path.Combine(directoryName, xAttribute.Value);
                            XDocument  xDocument  = XDocument.Load(path);
                            valueList.Add(ConvertValue(type, xDocument.ToString()));
                        }

                        // A 'load' element will read a binary resource into a byte array.
                        if (xElement.Name == "load")
                        {
                            XAttribute xAttribute = xElement.Attribute("path");
                            String     path       = Path.IsPathRooted(xAttribute.Value) ? xAttribute.Value : Path.Combine(directoryName, xAttribute.Value);
                            Byte[]     binaryData;
                            using (FileStream fileStream = new FileStream(path, FileMode.Open, FileAccess.Read))
                            {
                                binaryData = new Byte[fileStream.Length];
                                fileStream.Read(binaryData, 0, Convert.ToInt32(fileStream.Length));
                            }
                            return(ConvertValue(type, Convert.ToBase64String(binaryData)));
                        }
                    }
                }

                // This array is most often used as a key to find a record in a table.
                return(valueList.ToArray());
            }
            else
            {
                // If the XML specifies an override for the native data type of the parameter, make sure that the new value's type is compatible with the parameter.
                Type originalType = type;
                type = ScriptLoader.GetElementType(type, parameterElement);
                if (type != originalType && !type.IsSubclassOf(originalType))
                {
                    throw new Exception(String.Format("Can't cast a parameter of type {0} to {1}.", type, originalType));
                }

                // It is possible to specify the value using the content of an XML element or through an "import" statement.  This will cycle through any nodes of
                // the parameter looking for additional nodes containing the data for the parameter.  Of course, for a scalar, there is only a single value that
                // can be returned, so we'll take the first element we find that converts into a value.
                foreach (XObject xObject in parameterElement.DescendantNodes())
                {
                    return(ScriptLoader.ParseValue(type, xObject, directoryName));
                }

                // If no elements are specified, then we'll simply convert the attribute into a value for this parameter.  This is by far the most common method of
                // providing values for parameter.
                XAttribute valueAttribute = parameterElement.Attribute("value");
                return(valueAttribute == null ? DBNull.Value : ScriptLoader.ConvertValue(type, valueAttribute.Value));
            }
        }