Example #1
0
        }   // public static char LastCharacterOfString


        /// <summary>
        /// Returns the character at the Nth position in a string.
        /// </summary>
        /// <param name="pstrIn">
        /// Specify the string from which to return the last character.
        /// </param>
        /// <param name="pintOrdinalPosition">
        /// Specify the ordinal position of the desired character. Unlike array
        /// subscripts, which start at zero, ordinals start at one.
        /// </param>
        /// <returns>
        /// Unless the input string is empty (or null), or pintOrdinalPosition
        /// is less than 1 or greater than the length of the string, the return
        /// value is the character at the specified (Nth) position.
        /// 
        /// If the function cannot return the requested character, the return
        /// value is SpecialCharacters.NUL, the null character.
        /// </returns>
        public static char NthCharacterOfString (
            string pstrIn ,
            int pintOrdinalPosition )
        {
            if ( string.IsNullOrEmpty ( pstrIn ) )
                return SpecialCharacters.NULL_CHAR;
            else
                if ( pintOrdinalPosition <= ArrayInfo.ARRAY_FIRST_ELEMENT || pintOrdinalPosition > pstrIn.Length )
                    return SpecialCharacters.NULL_CHAR;
                else
                    return pstrIn [ ArrayInfo.IndexFromOrdinal ( pintOrdinalPosition ) ];
        }   // public static char NthCharacterOfString
Example #2
0
        }   // private int FixThisItem


        /// <summary>
        /// This private static method encapsulates the work of loading an
        /// embedded text file resource that consists of tab delimited strings,
        /// and parsing them into pairs of strrings.
        /// </summary>
        /// <param name="pstrEmbeddedResourceName">
        /// This string is expected to contain the unqualified name of the
        /// embedded text file resource, which is easy to grab from the Solution
        /// Explorer. This routine appends the extension, which must be .txt.
        /// </param>
        /// <returns>
        /// The return value is an array of StringFixups.StringFixup objects,
        /// each consisting of a pair of strings, one being a string for which
        /// to search, while its companion is the replacement string.
        /// </returns>
        private static StringFixups.StringFixup [ ] LoadStringFixups ( string pstrEmbeddedResourceName )
        {
            const string LABEL_ROW = @"JSON	VS";
            const string TSV_EXTENSION = @".txt";

            const int STRING_PER_RESPONSE = ArrayInfo.ARRAY_FIRST_ELEMENT;
            const int STRING_FOR_JSONCONVERTER = STRING_PER_RESPONSE + ArrayInfo.NEXT_INDEX;
            const int EXPECTED_FIELD_COUNT = STRING_FOR_JSONCONVERTER + ArrayInfo.NEXT_INDEX;

            string strEmbeddResourceFileName = string.Concat (
                pstrEmbeddedResourceName ,
                TSV_EXTENSION );
            string [ ] astrAllMapItems = Readers.LoadTextFileFromEntryAssembly ( strEmbeddResourceFileName );
            Parser parser = new Parser (
                CSVParseEngine.DelimiterChar.Tab ,
                CSVParseEngine.GuardChar.DoubleQuote ,
                CSVParseEngine.GuardDisposition.Strip );
            StringFixups.StringFixup [ ] rFunctionMaps = new StringFixups.StringFixup [ ArrayInfo.IndexFromOrdinal ( astrAllMapItems.Length ) ];

            for ( int intI = ArrayInfo.ARRAY_FIRST_ELEMENT ;
                      intI < astrAllMapItems.Length ;
                      intI++ )
            {
                if ( intI == ArrayInfo.ARRAY_FIRST_ELEMENT )
                {
                    if ( astrAllMapItems [ intI ] != LABEL_ROW )
                    {
                        throw new Exception (
                            string.Format (
                                Properties.Resources.ERRMSG_CORRUPTED_EMBBEDDED_RESOURCE_LABEL ,
                                new string [ ]
                                {
                                    strEmbeddResourceFileName ,                 // Format Item 0: internal resource {0}
                                    LABEL_ROW ,                                 // Format Item 1: Expected value = {1}
                                    astrAllMapItems [ intI ] ,                  // Format Item 2: Actual value   = {2}
                                    Environment.NewLine                         // Format Item 3: Platform-specific newline
                                } ) );
                    }   // if ( astrAllMapItems[intI] != LABEL_ROW )
                }   // TRUE (label row sanity check 1 of 2) block, if ( intI == ArrayInfo.ARRAY_FIRST_ELEMENT )
                else
                {
                    string [ ] astrFields = parser.Parse ( astrAllMapItems [ intI ] );

                    if ( astrFields.Length == EXPECTED_FIELD_COUNT )
                    {
                        rFunctionMaps [ ArrayInfo.IndexFromOrdinal ( intI ) ] = new StringFixups.StringFixup (
                            astrFields [ STRING_PER_RESPONSE ] ,
                            astrFields [ STRING_FOR_JSONCONVERTER ] );
                    }   // TRUE (anticipated outcome) block, if ( astrFields.Length == EXPECTED_FIELD_COUNT )
                    else
                    {
                        throw new Exception (
                            string.Format (
                                Properties.Resources.ERRMSG_CORRUPTED_EMBEDDED_RESOURCE_DETAIL ,
                                new object [ ]
                                {
                                    intI ,                                      // Format Item 0: Detail record {0}
                                    strEmbeddResourceFileName ,                 // Format Item 1: internal resource {1}
                                    EXPECTED_FIELD_COUNT ,                      // Format Item 2: Expected field count = {2}
                                    astrFields.Length ,                         // Format Item 3: Actual field count   = {3}
                                    astrAllMapItems [ intI ] ,                  // Format Item 4: Actual record        = {4}
                                    Environment.NewLine                         // Format Item 5: Platform-specific newline
                                } ) );
                    }   // FALSE (unanticipated outcome) block, if ( astrFields.Length == EXPECTED_FIELD_COUNT )
                }   // FALSE (detail row) block, if ( intI == ArrayInfo.ARRAY_FIRST_ELEMENT )
            }   // for ( int intI = ArrayInfo.ARRAY_FIRST_ELEMENT ; intI < astrAllMapItems.Length ; intI++ )

            return rFunctionMaps;
        }   // private static StringFixups.StringFixup [ ] GetSStringFixups
		}   // private void InitializeOnFirstUse


		/// <summary>
		/// This method creates a generic dictionary of ParameterTypeInfo
		/// objects, keyed by parameter name from an array of strings, each of which
		/// is the internal name of a parameter.
		/// </summary>
		/// <param name="pastrParameterTypeInfoArray">
		/// This array of strings is a list of parameter names and property
		/// values, such as generic ParameterType enumeration values, that is
		/// read from a TAB delimited text file that is stored in an embeddede
		/// assembly resource.
		/// 
		/// The first string is expected to be a label row that maps the fields
		/// in the remaining strings to their values.
		/// </param>
		/// <returns>
		/// If it succeeds, the return value is a populated dictionary of 
		/// ParameterTypeInfo objects keyed by their internal parameter names.
		/// Invalid data or a corrupted parameter resource file causes the
		/// ParameterTypeInfo constructor to throw an InvalidOperationException.
		/// </returns>
		/// <exception cref="InvalidOperationException">
		/// A detailed InvalidOperationException exception report arises if the
		/// array of parameters is invalid.
		/// 
		/// Correct code should never throw this exception.
		/// </exception>
		private Dictionary<string , ParameterTypeInfo<T>> GetParameterTypeInfo ( string [ ] pastrParameterTypeInfoArray )
		{
			Dictionary<string , ParameterTypeInfo<T>> rdctParameterTypeInfo = new Dictionary<string , ParameterTypeInfo<T>> ( ArrayInfo.IndexFromOrdinal ( pastrParameterTypeInfoArray.Length ) );

			for ( int intPosition = ArrayInfo.ARRAY_SECOND_ELEMENT ;
					  intPosition < pastrParameterTypeInfoArray.Length ;
					  intPosition++ )
			{
				ParameterTypeInfo<T> pti = new ParameterTypeInfo<T> (
					pastrParameterTypeInfoArray [ intPosition ] ,                       // string pstrParameterInfoDetail
					pastrParameterTypeInfoArray [ ArrayInfo.ARRAY_FIRST_ELEMENT ] );    // string pastrParameterInfoColumnNames
				rdctParameterTypeInfo.Add (
					pti.ParameterName ,                                                 // Key
					pti );                                                              // Value
			}   // for ( int intPosition = ArrayInfo.ARRAY_SECOND_ELEMENT ; intPosition < pastrParameterTypeInfoArray.Length ; intPosition++ )

			return rdctParameterTypeInfo;
		}   // GetParameterTypeInfo
        }   // public string GetDLLSetting


		/// <summary>
		/// Set the like named properties from the linked configuration file.
		/// </summary>
		/// <param name="pderivedType">
		/// When the derived class constructor calls this method, it must pass in a
		/// reference to its own Type property.
		/// </param>
		/// <returns>
		/// The return value is the count of properties that were set.
		/// </returns>
		/// <remarks>
		/// This can almost certainly be simplified by enumerating the settings,
		/// but either way risks a NOT FOUND exception.
		/// 
		/// This method uses some fairly tricky Reflection gymnastics to map the
		/// key names in a configuration file to property names on an object.
		/// </remarks>
		protected PropertySourceCounts SetPropertiesFromDLLConfiguration ( Type pderivedType )
		{
			const BindingFlags BASELINE_BINDING_FLAGS = BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public;

            PropertySourceCounts rutpCounts = new PropertySourceCounts ( );

            rutpCounts.Defaulted = MagicNumbers.ZERO;
            rutpCounts.SpecifiedInConfiguration = MagicNumbers.ZERO;

            string [ ] astrDefaultErrorMessageColors = DLLSettings.AllKeys;

			for ( int intJ = ArrayInfo.ARRAY_FIRST_ELEMENT ;
					  intJ < astrDefaultErrorMessageColors.Length ;
					  intJ++ )
			{
				string strPropertyName = null;                                  // This must be visible to the catch block.

                try
                {
                    strPropertyName = astrDefaultErrorMessageColors [ intJ ];
                    string strConfigValueString = DLLSettings [ strPropertyName ].Value;
                    TraceLogger.WriteWithBothTimesLabeledLocalFirst (
                        string.Format (
                            @"At iteration {0} in {1}: {2} = {3}" ,             // Format control string
                            new object [ ]                                      // Array of values to substitute for tokens in format control string
                            {
                                ArrayInfo.OrdinalFromIndex ( intJ ) ,           // Format Item 0: At iteration {0}
                                MethodBase.GetCurrentMethod ( ).Name ,          // Format Item 1: in {1}
                                strPropertyName ,                               // Format Item 2: : {2}
                                strConfigValueString                            // Format Item 3: = {3}
                            } ) );
                    PropertyInfo piThisProperty = this.GetType ( ).GetProperty (
                        strPropertyName ,                                       // string      name         = The string containing the name of the property to get
                        BASELINE_BINDING_FLAGS );                               // bindingAttr BindingFlags = A bitmask comprised of one or more BindingFlags that specify how the search is conducted

                    if ( piThisProperty != null )
                    {
                        piThisProperty.SetValue (
                            this ,                                                  // Object      obj          = Object to which to apply setting
                            FromString (
                                piThisProperty ,
                                strConfigValueString ) ,                            // Object      value        = Value to assign to the property to which piThisProperty refers
                            BASELINE_BINDING_FLAGS | BindingFlags.SetProperty ,     // invokeAttr  invokeAtt	= A bitwise combination of the following enumeration members that specify the invocation attribute: InvokeMethod, reateInstance, Static, GetField, SetField, GetProperty, or SetProperty. You must specify a suitable invocation attribute.
                            null ,                                                  // Binder      binder		= An object that enables the binding, coercion of argument types, invocation of members, and retrieval of MemberInfo objects through reflection. If binder is null, the default binder is used.
                            null ,                                                  // Object[]    index		= Optional index values for indexed properties. This value should be null for non-indexed properties.
                            null );                                                 // CultureInfo culture		= The culture for which the resource is to be localized. If the resource is not localized for this culture, the Parent property will be called successively in search of a match. If this value is null, the culture-specific information is obtained from the CurrentUICulture property.
                        rutpCounts.SpecifiedInConfiguration++;                      // Count properties successfully set; the final value is returned as the function value.
                    }   // TRUE (The configuration file has a value for this property.) block, if ( piThisProperty != null )
                    else
                    {
                        MissingConfigSettings = MissingConfigSettings ?? UnconfiguredDLLSettings.TheOnlyInstance;

                        MissingConfigSettings.Add (
                            Path.GetFileName ( _strAssemblyLocation ) ,
                                strPropertyName ,                               // Format Item 0: property {1} default value
                                strConfigValueString );                         // Format Item 1: default value of {2} accepted
                        rutpCounts.Defaulted++;                                 // Count properties that retained their hard coded default values.
                    }   // FALSE (A value for this property is absent from the configuration file.) block, if ( piThisProperty != null )
                }
                catch ( Exception exAllKinds )
                {	// Since the catch block is within the body of the For loop, processing advances to the next item.
                    TraceLogger.WriteWithBothTimesLabeledLocalFirst (
                        string.Format (
                            @"{0}.{1} = {2}" ,
                            nameof ( Environment ) ,
                            nameof ( Environment.StackTrace ) ,
                            Environment.StackTrace ) );
                    if ( RecoveredConfigurationExceptions == null )
                    {   // Create as and when needed.
                        RecoveredConfigurationExceptions = new System.Collections.Generic.List<RecoveredException> ( );
                    }   // if ( RecoveredConfigurationExceptions == null )

                    RecoveredConfigurationExceptions.Add (
                       new RecoveredException (
                           string.Format (
                               Properties.Resources.ERRMSG_EXCEPTION_NOT_THROWN ,
                               SaveErrorReport (
                                   this.GetType ( ) ,
                                   strPropertyName ,
                                   exAllKinds ).Message ) ,
                           exAllKinds.Source ,
                           exAllKinds.StackTrace ,
                           exAllKinds.TargetSite.Name ) );
                    Exception exWrapped = RecoveredConfigurationExceptions [ ArrayInfo.IndexFromOrdinal ( RecoveredConfigurationExceptions.Count ) ];
                    TraceLogger.WriteWithBothTimesLabeledLocalFirst (
                        string.Format (
                            Properties.Resources.TRACEMSG_EXCEPTION_NOT_THROWN_1 ,
                            exWrapped.Message ) );
                    TraceLogger.WriteWithBothTimesLabeledLocalFirst (
                        string.Format (
                            Properties.Resources.TRACEMSG_EXCEPTION_NOT_THROWN_2 ,
                            exWrapped.Source ?? Common.Properties.Resources.MSG_OBJECT_REFERENCE_IS_NULL ) );
                    TraceLogger.WriteWithBothTimesLabeledLocalFirst (
                        string.Format (
                            Properties.Resources.TRACEMSG_EXCEPTION_NOT_THROWN_3 ,
                            exWrapped.TargetSite != null
                                ? exWrapped.TargetSite.Name
                                : Common.Properties.Resources.MSG_OBJECT_REFERENCE_IS_NULL ) );
                    TraceLogger.WriteWithBothTimesLabeledLocalFirst (
                        string.Format (
                            Properties.Resources.TRACEMSG_EXCEPTION_NOT_THROWN_4 ,
                            exWrapped.StackTrace ?? Common.Properties.Resources.MSG_OBJECT_REFERENCE_IS_NULL ) );

                    //  --------------------------------------------------------
                    //  Since SaveErrorReport appends the inner exception, this
                    //  test is technically redundant, but I chose to leave it,
                    //  as a reminder that new exceptions are not necessarily
                    //  so decordated. Hence, with the test, this code is a bit
                    //  more portable.
                    //  --------------------------------------------------------

                    if ( exWrapped.InnerException != null )
                    {
                        TraceLogger.WriteWithBothTimesLabeledLocalFirst (
                        string.Format (
                            Properties.Resources.TRACEMSG_EXCEPTION_NOT_THROWN_5 ,
                            exWrapped.InnerException.Message ?? Common.Properties.Resources.MSG_OBJECT_REFERENCE_IS_NULL ) );
                        TraceLogger.WriteWithBothTimesLabeledLocalFirst (
                            string.Format (
                                Properties.Resources.TRACEMSG_EXCEPTION_NOT_THROWN_6 ,
                                exWrapped.InnerException.Source ?? Common.Properties.Resources.MSG_OBJECT_REFERENCE_IS_NULL ) );
                        TraceLogger.WriteWithBothTimesLabeledLocalFirst (
                            string.Format (
                                Properties.Resources.TRACEMSG_EXCEPTION_NOT_THROWN_7 ,
                                exWrapped.InnerException.TargetSite.Name ?? Common.Properties.Resources.MSG_OBJECT_REFERENCE_IS_NULL ) );
                        TraceLogger.WriteWithBothTimesLabeledLocalFirst (
                            string.Format (
                                Properties.Resources.TRACEMSG_EXCEPTION_NOT_THROWN_8 ,
                                exWrapped.InnerException.StackTrace ?? Common.Properties.Resources.MSG_OBJECT_REFERENCE_IS_NULL ) );
                    }   // TRUE (anticipated outcome) block, if ( exWrapped.InnerException != null )
                    else
                    {
                        TraceLogger.WriteWithBothTimesLabeledLocalFirst ( Properties.Resources.TRACEMSG_EXCEPTION_NOT_THROWN_9 );
                    }   // FALSE (unanticipated outcome) block, if ( exWrapped.InnerException != null )
                }   // catch ( Exception exAllKinds )
            }   // for ( int intJ = ArrayInfo.ARRAY_FIRST_ELEMENT ; intJ < astrDefaultErrorMessageColors.Length ; intJ++ )

            return rutpCounts;
		}	// SetPropertiesFromDLLConfiguration