Big changes

This commit is contained in:
Duc
2025-03-13 12:04:22 -07:00
parent c689fcb7f9
commit ffa9905494
748 changed files with 199255 additions and 3743 deletions

View File

@@ -0,0 +1,192 @@
// **********************************************************************************************************
// AutomationMessage.cs
// 1/8/2024
// NGI - Next Generation Interceptor
//
// Contract No. HQ0856-21-C-0003/1022000209
//
// THIS DOCUMENT DOES NOT CONTAIN TECHNOLOGY OR TECHNICAL DATA CONTROLLED UNDER EITHER THE U.S.
// INTERNATIONAL TRAFFIC IN ARMS REGULATIONS OR THE U.S. EXPORT ADMINISTRATION REGULATIONS.
//
// RAYTHEON PROPRIETARY: THIS DOCUMENT CONTAINS DATA OR INFORMATION PROPRIETARY TO RAYTHEON
// COMPANY AND IS RESTRICTED TO USE ONLY BY PERSONS AUTHORIZED BY RAYTHEON COMPANY IN WRITING TO USE IT.
// DISCLOSURE TO UNAUTHORIZED PERSONS WOULD LIKELY CAUSE SUBSTANTIAL COMPETITIVE HARM TO RAYTHEON
// COMPANY'S BUSINESS POSITION. NEITHER SAID DOCUMENT NOR ITS CONTENTS SHALL BE FURNISHED OR DISCLOSED
// TO OR COPIED OR USED BY PERSONS OUTSIDE RAYTHEON COMPANY WITHOUT THE EXPRESS WRITTEN APPROVAL OF
// RAYTHEON COMPANY.
//
// UNPUBLISHED WORK - COPYRIGHT RAYTHEON COMPANY.
//
// DESTRUCTION NOTICE: FOR CLASSIFIED DOCUMENTS FOLLOW THE PROCEDURES IN DOD 5220.22-M,
// NATIONAL INDUSTRIAL SECURITY PROGRAM OPERATING MANUAL, FEBRUARY 2006,
// INCORPORATING CHANGE 1, MARCH 28, 2013, CHAPTER 5, SECTION 7, OR DODM 5200.01-VOLUME 3,
// DOD INFORMATION SECURITY PROGRAM: PROTECTION OF CLASSIFIED INFORMATION, ENCLOSURE 3,
// SECTION 17. FOR CONTROLLED UNCLASSIFIED INFORMATION FOLLOW THE PROCEDURES IN DODM 5200.01-VOLUME 4,
// INFORMATION SECURITY PROGRAM: CONTROLLED UNCLASSIFIED INFORMATION.
//
// CONTROLLED BY: MISSILE DEFENSE AGENCY
// CONTROLLED BY: GROUND-BASED MIDCOURSE DEFENSE PROGRAM OFFICE
// CUI CATEGORY: CTI
// DISTRIBUTION/DISSEMINATION CONTROL: F
// POC: Alex Kravchenko (1118268)
// **********************************************************************************************************
using System;
namespace Raytheon.Common
{
/// <summary>
/// An abstract base class for AutomationMessages that go between the client and server
/// </summary>
public abstract class AutomationMessage : ICloneable
{
#region PrivateClassMembers
private string _description;
protected AutomationMessageHeader _header;
#endregion
#region PrivateClassFunctions
/// <summary>
/// The constructor
/// </summary>
/// <param name="AutomationMessageId">The AutomationMessage id</param>
/// <param name="description">The AutomationMessage description</param>
/// <param name="messageId">The number of bytes in the payload of the AutomationMessage. (The number of bytes in the child class)</param>
protected AutomationMessage(uint messageId, string description, uint messageLength)
{
_description = description;
_header = new AutomationMessageHeader(messageId, messageLength);
}
/// <summary>
/// Copy Constructor
/// </summary>
/// <param name="message">The AutomationMessage to copy from</param>
protected AutomationMessage(AutomationMessage message)
{
_header = new AutomationMessageHeader(message._header);
_description = message._description;
}
/// <summary>
/// Sets the number of bytes in the entire AutomationMessage, including header.
/// Some times when receiving a AutomationMessage, you must instantiate the object before you know how many bytes the AutomationMessage is
/// </summary>
/// <param name="messageLength">The number of bytes in the entire AutomationMessage</param>
protected void SetMessageLen(uint messageLength)
{
_header.SetMessageLen(messageLength);
}
/// <summary>
/// abstract function for children to implement a clone of their object
/// </summary>
/// <returns></returns>
protected abstract object CloneSelf();
/// <summary>
/// abstract function for children to implement the function that they serve
/// </summary>
public abstract void ExecuteMsg();
/// <summary>
/// abstract function for children to implement the formatting of their parameters
/// </summary>
/// <param name="pData"></param>
protected abstract void FormatData(IntPtr pData);
/// <summary>
/// abstract function for children to implement the parsing of their parameters
/// </summary>
/// <param name="pData"></param>
protected abstract void ParseData(IntPtr pData);
#endregion
#region PublicClassFunctions
/// <summary>
/// Get a copy of the AutomationMessage object
/// </summary>
/// <returns></returns>
public object Clone()
{
// tell the child to clone itself
return this.CloneSelf();
}
/// <summary>
/// Encode the AutomationMessage into a byte array for sending
/// </summary>
/// <param name="pData">The buffer to put the AutomationMessage items</param>
public void Format(IntPtr pData)
{
_header.Format(pData);
IntPtr pPayload = IntPtr.Add(pData, (int)GetHeaderLength());
// ask child class to format its data
FormatData(pPayload);
}
/// <summary>
/// Getter
/// </summary>
/// <returns>The description</returns>
public string GetDescription()
{
return _description;
}
/// <summary>
/// Getter
/// </summary>
/// <returns>The number of bytes in the AutomationMessage, including header</returns>
public uint GetEntireMsgLength()
{
return _header.GetEntireMsgLength();
}
/// <summary>
/// getter
/// </summary>
/// <returns>The id</returns>
public uint GetMessageId()
{
return _header.GetMessageId();
}
/// <summary>
/// getter
/// </summary>
/// <returns>The number of bytes in the head</returns>
public uint GetHeaderLength()
{
return _header.GetHeaderLength();
}
/// <summary>
/// Takes an array of bytes and populates the AutomationMessage object
/// </summary>
/// <param name="pData">The AutomationMessage in byte form</param>
public void Parse(IntPtr pData)
{
_header.Parse(pData);
IntPtr pPayLoad = IntPtr.Add(pData, (int)GetHeaderLength());
ParseData(pPayLoad);
}
/// <summary>
/// Convert this AutomationMessage into string form
/// </summary>
/// <returns>The AutomationMessage in string form</returns>
public override string ToString()
{
return "Description: " + GetDescription() + "\n" + _header.ToString();
}
#endregion
}
}

View File

@@ -0,0 +1,160 @@
// **********************************************************************************************************
// AutomationMessageHeader.cs
// 1/8/2024
// NGI - Next Generation Interceptor
//
// Contract No. HQ0856-21-C-0003/1022000209
//
// THIS DOCUMENT DOES NOT CONTAIN TECHNOLOGY OR TECHNICAL DATA CONTROLLED UNDER EITHER THE U.S.
// INTERNATIONAL TRAFFIC IN ARMS REGULATIONS OR THE U.S. EXPORT ADMINISTRATION REGULATIONS.
//
// RAYTHEON PROPRIETARY: THIS DOCUMENT CONTAINS DATA OR INFORMATION PROPRIETARY TO RAYTHEON
// COMPANY AND IS RESTRICTED TO USE ONLY BY PERSONS AUTHORIZED BY RAYTHEON COMPANY IN WRITING TO USE IT.
// DISCLOSURE TO UNAUTHORIZED PERSONS WOULD LIKELY CAUSE SUBSTANTIAL COMPETITIVE HARM TO RAYTHEON
// COMPANY'S BUSINESS POSITION. NEITHER SAID DOCUMENT NOR ITS CONTENTS SHALL BE FURNISHED OR DISCLOSED
// TO OR COPIED OR USED BY PERSONS OUTSIDE RAYTHEON COMPANY WITHOUT THE EXPRESS WRITTEN APPROVAL OF
// RAYTHEON COMPANY.
//
// UNPUBLISHED WORK - COPYRIGHT RAYTHEON COMPANY.
//
// DESTRUCTION NOTICE: FOR CLASSIFIED DOCUMENTS FOLLOW THE PROCEDURES IN DOD 5220.22-M,
// NATIONAL INDUSTRIAL SECURITY PROGRAM OPERATING MANUAL, FEBRUARY 2006,
// INCORPORATING CHANGE 1, MARCH 28, 2013, CHAPTER 5, SECTION 7, OR DODM 5200.01-VOLUME 3,
// DOD INFORMATION SECURITY PROGRAM: PROTECTION OF CLASSIFIED INFORMATION, ENCLOSURE 3,
// SECTION 17. FOR CONTROLLED UNCLASSIFIED INFORMATION FOLLOW THE PROCEDURES IN DODM 5200.01-VOLUME 4,
// INFORMATION SECURITY PROGRAM: CONTROLLED UNCLASSIFIED INFORMATION.
//
// CONTROLLED BY: MISSILE DEFENSE AGENCY
// CONTROLLED BY: GROUND-BASED MIDCOURSE DEFENSE PROGRAM OFFICE
// CUI CATEGORY: CTI
// DISTRIBUTION/DISSEMINATION CONTROL: F
// POC: Alex Kravchenko (1118268)
// **********************************************************************************************************
using System;
using System.Runtime.InteropServices;
namespace Raytheon.Common
{
/// <summary>
/// The header for all messages
/// </summary>
public class AutomationMessageHeader
{
#region PublicClassMembers
public const int HEADER_EXPECTED_SIZE = 8;
#endregion
#region PrivateClassMembers
[StructLayout(LayoutKind.Sequential, Pack = 1)]
private struct HeaderStruct
{
public uint messageId;
public uint messageLength;// total msg size in bytes..Including the header.
};
private HeaderStruct _headerStruct;
#endregion
#region PublicClassFunctions
/// <summary>
/// Copy constructor
/// </summary>
/// <param name="header">The header to copy</param>
public AutomationMessageHeader(AutomationMessageHeader header)
{
_headerStruct = new HeaderStruct();
_headerStruct = header._headerStruct;
}
/// <summary>
/// Constructor for when receiving data.
/// Use this constructor and then parse to populate it
/// </summary>
public AutomationMessageHeader()
{
_headerStruct = new HeaderStruct();
}
/// <summary>
/// Constructor for sending
/// </summary>
/// <param name="msgId">the message id</param>
/// <param name="messageLength">The number of bytes in the message, not including the header</param>
public AutomationMessageHeader(uint msgId, uint messageLength)
{
_headerStruct = new HeaderStruct
{
messageId = msgId,
messageLength = messageLength + GetHeaderLength()
};
}
/// <summary>
/// Encode the header into a byte array for sending
/// </summary>
/// <param name="pData">The buffer to put the message items</param>
public void Format(IntPtr pData)
{
Marshal.StructureToPtr(_headerStruct, pData, true);
}
/// <summary>
/// Getter
/// </summary>
/// <returns>The number of bytes in the message, including header</returns>
public uint GetEntireMsgLength()
{
return _headerStruct.messageLength;
}
/// <summary>
/// getter
/// </summary>
/// <returns>The id</returns>
public uint GetMessageId()
{
return _headerStruct.messageId;
}
/// <summary>
/// getter
/// </summary>
/// <returns>The header length in bytes</returns>
public uint GetHeaderLength()
{
return (uint)Marshal.SizeOf(_headerStruct);
}
/// <summary>
/// Takes an array of bytes and populates the header object
/// </summary>
/// <param name="pData">The header in byte form</param>
public void Parse(IntPtr pData)
{
_headerStruct = (HeaderStruct)Marshal.PtrToStructure(pData, typeof(HeaderStruct));
}
/// <summary>
///
/// </summary>
/// <param name="messageLength"></param>
public void SetMessageLen(uint messageLength)
{
_headerStruct.messageLength = messageLength + GetHeaderLength();
}
/// <summary>
/// Creates a string version of the header members
/// </summary>
/// <returns>A string containing the header data</returns>
public override string ToString()
{
string msg = "Header Data:\r\n";
msg += "msg id: " + Convert.ToString(_headerStruct.messageId) + "\r\n";
msg += "msg len: " + Convert.ToString(_headerStruct.messageLength) + "\r\n";
return msg;
}
#endregion
}
}

View File

@@ -0,0 +1,198 @@
// ******************************************************************************//
// RAYTHEON PROPRIETARY: THIS DOCUMENT CONTAINS DATA OR INFORMATION
// PROPRIETARY TO RAYTHEON COMPANY AND IS RESTRICTED TO USE ONLY BY PERSONS
// AUTHORIZED BY RAYTHEON COMPANY IN WRITING TO USE IT. DISCLOSURE TO
// UNAUTHORIZED PERSONS WOULD LIKELY CAUSE SUBSTANTIAL COMPETITIVE HARM TO
// RAYTHEON COMPANY''S BUSINESS POSITION. NEITHER SAID DOCUMENT NOR ITS
// CONTENTS SHALL BE FURNISHED OR DISCLOSED TO OR COPIED OR USED BY PERSONS
// OUTSIDE RAYTHEON COMPANY WITHOUT THE EXPRESS WRITTEN APPROVAL OF RAYTHEON
// COMPANY.
//
// THIS PROPRIETARY NOTICE IS NOT APPLICABLE IF DELIVERED TO THE U.S. GOVERNMENT
//
// UNPUBLISHED WORK - COPYRIGHT RAYTHEON COMPANY.
//
// WARNING: THIS DOCUMENT CONTAINS TECHNICAL DATA AND / OR TECHNOLOGY WHOSE
// EXPORT OR DISCLOSURE TO NON-U.S. PERSONS, WHEREVER LOCATED, IS RESTRICTED
// BY THE INTERNATIONAL TRAFFIC IN ARMS REGULATIONS (ITAR) (22 C.F.R. SECTION
// 120-130) OR THE EXPORT ADMINISTRATION REGULATIONS (EAR) (15 C.F.R. SECTION
// 730-774). THIS DOCUMENT CANNOT BE EXPORTED (E.G., PROVIDED TO A SUPPLIER
// OUTSIDE OF THE UNITED STATES) OR DISCLOSED TO A NON-U.S. PERSON, WHEREVER
// LOCATED, UNTIL A FINAL JURISDICTION AND CLASSIFICATION DETERMINATION HAS
// BEEN COMPLETED AND APPROVED BY RAYTHEON, AND ANY REQUIRED U.S. GOVERNMENT
// APPROVALS HAVE BEEN OBTAINED. VIOLATIONS ARE SUBJECT TO SEVERE CRIMINAL
// PENALTIES.
//
// DOD 5220.22-M, INDUSTRIAL SECURITY MANUAL, CHAPTER 5, SECTION 1 THROUGH 9 :
// FOR CLASSIFIED DOCUMENTS FOLLOW THE PROCEDURES IN OR DOD 5200.1-R,
// INFORMATION SECURITY PROGRAM, CHAPTER 6. FOR UNCLASSIFIED, LIMITED DOCUMENTS
// DESTROY BY ANY METHOD THAT WILL PREVENT DISCLOSURE OF CONTENTS OR
// RECONSTRUCTION OF THE DOCUMENT.
// ****************************************************************************//
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Newtonsoft.Json;
namespace Raytheon.Common
{
/// <summary>
/// Implementation of the IConfigurationFile interface for Json file format
/// </summary>
public class JsonConfigurationFile : ConfigurationFileBase
{
private Dictionary<string, Dictionary<string, string>> _data;
/// <summary>
/// constructor
/// </summary>
/// <param name="fileName"></param>
/// <exception cref="ArgumentException"></exception>
public JsonConfigurationFile(string fileName)
: base(fileName)
{
if (_configurationType != ConfigurationFileType.JSON)
{
throw new ArgumentException("Expecting JSON file configuration type");
}
if (!_fileInfo.Exists)
{
using (File.Create(_fileInfo.FullName)) { }
}
}
/// <summary>
/// reads all available keys from given section from current configuration file
/// </summary>
/// <param name="section"></param>
/// <returns></returns>
public override List<string> ReadAllKeys(string section)
{
string json = File.ReadAllText(_fileName);
if (!string.IsNullOrEmpty(json))
{
_data = JsonConvert.DeserializeObject<Dictionary<string, Dictionary<string, string>>>(json);
}
else
{
_data = new Dictionary<string, Dictionary<string, string>>();
}
return _data.ContainsKey(section) ? _data[section].Keys.ToList() : new List<string>();
}
/// <summary>
/// reads all available sections from current configuration file
/// </summary>
/// <returns>list of sections</returns>
public override List<string> ReadAllSections()
{
string json = File.ReadAllText(_fileName);
if (!string.IsNullOrEmpty(json))
{
_data = JsonConvert.DeserializeObject<Dictionary<string, Dictionary<string, string>>>(json);
}
else
{
_data = new Dictionary<string, Dictionary<string, string>>();
}
return _data.Keys.ToList();
}
public override List<T> ReadList<T>(string section, string key, IList<T> defList = null)
{
return ReadValue(section, key, defList).ToList();
}
/// <summary>
/// reads a single value in json format
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="section"></param>
/// <param name="key"></param>
/// <param name="defValue"></param>
/// <returns>configuration value</returns>
/// <exception cref="NotImplementedException"></exception>
public override T ReadValue<T>(string section, string key, T defValue = default)
{
string json = File.ReadAllText(_fileName);
if (!string.IsNullOrEmpty(json))
{
_data = JsonConvert.DeserializeObject<Dictionary<string, Dictionary<string, string>>>(json);
}
else
{
_data = new Dictionary<string, Dictionary<string, string>>();
}
if (_data.ContainsKey(section) && _data[section].ContainsKey(key))
{
return JsonConvert.DeserializeObject<T>(_data[section][key]);
}
else
{
WriteValue(section, key, defValue);
return defValue;
}
}
/// <summary>
/// reads a single value in json format
/// </summary>
/// <param name="section"></param>
/// <param name="key"></param>
/// <returns>configuration value</returns>
/// <exception cref="NotImplementedException"></exception>
public override string ReadValue(string section, string key)
{
throw new NotImplementedException();
}
/// <summary>
/// writes a list of values of any generic type
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="section"></param>
/// <param name="key"></param>
/// <param name="listToWrite"></param>
public override void WriteList<T>(string section, string key, IList<T> listToWrite)
{
WriteValue(section, key, listToWrite);
}
/// <summary>
/// writes a single value
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="section"></param>
/// <param name="key"></param>
/// <param name="lineToWrite"></param>
public override void WriteValue<T>(string section, string key, T lineToWrite)
{
string json = File.ReadAllText(_fileName);
if (!string.IsNullOrEmpty(json))
{
_data = JsonConvert.DeserializeObject<Dictionary<string, Dictionary<string, string>>>(json);
}
else
{
_data = new Dictionary<string, Dictionary<string, string>>();
}
if (!_data.ContainsKey(section))
{
_data[section] = new Dictionary<string, string>();
}
_data[section][key] = JsonConvert.SerializeObject(lineToWrite);
using (StreamWriter writer = new StreamWriter(_fileName, false))
{
writer.WriteLine(JsonConvert.SerializeObject(_data));
}
}
}
}

View File

@@ -0,0 +1,139 @@
// ******************************************************************************//
// RAYTHEON PROPRIETARY: THIS DOCUMENT CONTAINS DATA OR INFORMATION
// PROPRIETARY TO RAYTHEON COMPANY AND IS RESTRICTED TO USE ONLY BY PERSONS
// AUTHORIZED BY RAYTHEON COMPANY IN WRITING TO USE IT. DISCLOSURE TO
// UNAUTHORIZED PERSONS WOULD LIKELY CAUSE SUBSTANTIAL COMPETITIVE HARM TO
// RAYTHEON COMPANY''S BUSINESS POSITION. NEITHER SAID DOCUMENT NOR ITS
// CONTENTS SHALL BE FURNISHED OR DISCLOSED TO OR COPIED OR USED BY PERSONS
// OUTSIDE RAYTHEON COMPANY WITHOUT THE EXPRESS WRITTEN APPROVAL OF RAYTHEON
// COMPANY.
//
// THIS PROPRIETARY NOTICE IS NOT APPLICABLE IF DELIVERED TO THE U.S. GOVERNMENT
//
// UNPUBLISHED WORK - COPYRIGHT RAYTHEON COMPANY.
//
// WARNING: THIS DOCUMENT CONTAINS TECHNICAL DATA AND / OR TECHNOLOGY WHOSE
// EXPORT OR DISCLOSURE TO NON-U.S. PERSONS, WHEREVER LOCATED, IS RESTRICTED
// BY THE INTERNATIONAL TRAFFIC IN ARMS REGULATIONS (ITAR) (22 C.F.R. SECTION
// 120-130) OR THE EXPORT ADMINISTRATION REGULATIONS (EAR) (15 C.F.R. SECTION
// 730-774). THIS DOCUMENT CANNOT BE EXPORTED (E.G., PROVIDED TO A SUPPLIER
// OUTSIDE OF THE UNITED STATES) OR DISCLOSED TO A NON-U.S. PERSON, WHEREVER
// LOCATED, UNTIL A FINAL JURISDICTION AND CLASSIFICATION DETERMINATION HAS
// BEEN COMPLETED AND APPROVED BY RAYTHEON, AND ANY REQUIRED U.S. GOVERNMENT
// APPROVALS HAVE BEEN OBTAINED. VIOLATIONS ARE SUBJECT TO SEVERE CRIMINAL
// PENALTIES.
//
// DOD 5220.22-M, INDUSTRIAL SECURITY MANUAL, CHAPTER 5, SECTION 1 THROUGH 9 :
// FOR CLASSIFIED DOCUMENTS FOLLOW THE PROCEDURES IN OR DOD 5200.1-R,
// INFORMATION SECURITY PROGRAM, CHAPTER 6. FOR UNCLASSIFIED, LIMITED DOCUMENTS
// DESTROY BY ANY METHOD THAT WILL PREVENT DISCLOSURE OF CONTENTS OR
// RECONSTRUCTION OF THE DOCUMENT.
// ****************************************************************************//
// Ignore Spelling: Yaml
using System;
using System.Collections.Generic;
using System.IO;
namespace Raytheon.Common
{
public class YamlConfigurationFile : ConfigurationFileBase
{
//private Dictionary<string, Dictionary<string, string>> _data;
/// <summary>
/// constructor
/// </summary>
/// <param name="fileName"></param>
/// <exception cref="ArgumentException"></exception>
public YamlConfigurationFile(string fileName)
: base(fileName)
{
if (_configurationType != ConfigurationFileType.OTHER)
{
throw new ArgumentException("Expecting YAML file configuration type");
}
if (!_fileInfo.Exists)
{
using (File.Create(_fileInfo.FullName)) { }
}
}
/// <summary>
/// reads all available keys from given section from current configuration file
/// </summary>
/// <param name="section"></param>
/// <returns></returns>
public override List<string> ReadAllKeys(string section)
{
throw new NotImplementedException();
}
/// <summary>
/// reads all available sections from current configuration file
/// </summary>
/// <returns>list of sections</returns>
public override List<string> ReadAllSections()
{
throw new NotImplementedException();
}
public override List<T> ReadList<T>(string section, string key, IList<T> defList = null)
{
throw new NotImplementedException();
}
/// <summary>
/// reads a single value in yaml format
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="section"></param>
/// <param name="key"></param>
/// <param name="defValue"></param>
/// <returns>configuration value</returns>
/// <exception cref="NotImplementedException"></exception>
public override T ReadValue<T>(string section, string key, T defValue = default)
{
throw new NotImplementedException();
}
/// <summary>
/// reads a single value in json format
/// </summary>
/// <param name="section"></param>
/// <param name="key"></param>
/// <returns>configuration value</returns>
/// <exception cref="NotImplementedException"></exception>
public override string ReadValue(string section, string key)
{
throw new NotImplementedException();
}
/// <summary>
/// writes a list of values of any generic type
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="section"></param>
/// <param name="key"></param>
/// <param name="listToWrite"></param>
public override void WriteList<T>(string section, string key, IList<T> listToWrite)
{
throw new NotImplementedException();
}
/// <summary>
/// writes a single value
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="section"></param>
/// <param name="key"></param>
/// <param name="lineToWrite"></param>
public override void WriteValue<T>(string section, string key, T lineToWrite)
{
throw new NotImplementedException();
}
}
}

View File

@@ -0,0 +1,20 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Raytheon.Common
{
public class YamlConfigurationFileFactory : ConfigurationFileFactoryBase
{
/// <summary>
///
/// </summary>
/// <param name="fileName"></param>
/// <returns></returns>
public override IConfigurationFile CreateConfigurationFile(string fileName)
{
return new YamlConfigurationFile(fileName);
}
}
}

View File

@@ -0,0 +1,197 @@
// ******************************************************************************//
// RAYTHEON PROPRIETARY: THIS DOCUMENT CONTAINS DATA OR INFORMATION
// PROPRIETARY TO RAYTHEON COMPANY AND IS RESTRICTED TO USE ONLY BY PERSONS
// AUTHORIZED BY RAYTHEON COMPANY IN WRITING TO USE IT. DISCLOSURE TO
// UNAUTHORIZED PERSONS WOULD LIKELY CAUSE SUBSTANTIAL COMPETITIVE HARM TO
// RAYTHEON COMPANY''S BUSINESS POSITION. NEITHER SAID DOCUMENT NOR ITS
// CONTENTS SHALL BE FURNISHED OR DISCLOSED TO OR COPIED OR USED BY PERSONS
// OUTSIDE RAYTHEON COMPANY WITHOUT THE EXPRESS WRITTEN APPROVAL OF RAYTHEON
// COMPANY.
//
// THIS PROPRIETARY NOTICE IS NOT APPLICABLE IF DELIVERED TO THE U.S. GOVERNMENT
//
// UNPUBLISHED WORK - COPYRIGHT RAYTHEON COMPANY.
//
// WARNING: THIS DOCUMENT CONTAINS TECHNICAL DATA AND / OR TECHNOLOGY WHOSE
// EXPORT OR DISCLOSURE TO NON-U.S. PERSONS, WHEREVER LOCATED, IS RESTRICTED
// BY THE INTERNATIONAL TRAFFIC IN ARMS REGULATIONS (ITAR) (22 C.F.R. SECTION
// 120-130) OR THE EXPORT ADMINISTRATION REGULATIONS (EAR) (15 C.F.R. SECTION
// 730-774). THIS DOCUMENT CANNOT BE EXPORTED (E.G., PROVIDED TO A SUPPLIER
// OUTSIDE OF THE UNITED STATES) OR DISCLOSED TO A NON-U.S. PERSON, WHEREVER
// LOCATED, UNTIL A FINAL JURISDICTION AND CLASSIFICATION DETERMINATION HAS
// BEEN COMPLETED AND APPROVED BY RAYTHEON, AND ANY REQUIRED U.S. GOVERNMENT
// APPROVALS HAVE BEEN OBTAINED. VIOLATIONS ARE SUBJECT TO SEVERE CRIMINAL
// PENALTIES.
//
// DOD 5220.22-M, INDUSTRIAL SECURITY MANUAL, CHAPTER 5, SECTION 1 THROUGH 9 :
// FOR CLASSIFIED DOCUMENTS FOLLOW THE PROCEDURES IN OR DOD 5200.1-R,
// INFORMATION SECURITY PROGRAM, CHAPTER 6. FOR UNCLASSIFIED, LIMITED DOCUMENTS
// DESTROY BY ANY METHOD THAT WILL PREVENT DISCLOSURE OF CONTENTS OR
// RECONSTRUCTION OF THE DOCUMENT.
// ****************************************************************************//
using System;
using System.Collections.Generic;
namespace Raytheon.Common
{
/// <summary>
/// main class to be instantiated when working with configuration files
/// </summary>
public class ConfigurationFile : ConfigurationFileBase
{
/// <summary>
/// concrete implementation reference
/// </summary>
protected IConfigurationFile _configurationFile;
/// <summary>
/// Raytheon.Configuration will support INI and XML file formats.
/// For other formats have to use designated constructor
/// </summary>
/// <param name="fileName"></param>
/// <exception cref="InvalidOperationException"></exception>
public ConfigurationFile(string fileName)
: base(fileName)
{
if (!_fileInfo.Exists)
{
throw new Exception($"Can't find file: {fileName}");
}
var factory = GetFactory();
_configurationFile = factory.GetConfigurationFile(fileName);
}
/// <summary>
/// extension constructor, for other types based on the provided factory
/// </summary>
/// <param name="fileName"></param>
/// <param name="factory"></param>
public ConfigurationFile(string fileName, ConfigurationFileFactoryBase factory)
: base(fileName)
{
if (!_fileInfo.Exists)
{
throw new Exception($"Can't find file: {fileName}");
}
_configurationFile = factory.GetConfigurationFile(fileName);
}
/// <summary>
/// extension constructor, for other types based on provided type
/// </summary>
/// <param name="fileName"></param>
/// <param name="type"></param>
public ConfigurationFile(string fileName, string type)
: base(fileName)
{
if (!_fileInfo.Exists)
{
throw new Exception($"Can't find file: {fileName}");
}
ConfigurationFileFactory factory = new(type);
_configurationFile = factory.GetConfigurationFile(fileName);
}
/// <summary>
/// returns a factory based on file extension
/// </summary>
/// <returns></returns>
/// <exception cref="ArgumentException"></exception>
private static ConfigurationFileFactoryBase GetFactory()
{
ConfigurationFileType configurationType = ConfigurationTypeFromFileExtension(_fileInfo.Extension);
ConfigurationFileFactoryBase factory = configurationType switch
{
ConfigurationFileType.INI => new IniConfigurationFileFactory(),
ConfigurationFileType.XML => new XmlConfigurationFileFactory(),
ConfigurationFileType.JSON => new JsonConfigurationFileFactory(),
ConfigurationFileType.TOML => new TomlConfigurationFileFactory(),
_ => throw new ArgumentException($"Configuration Type ({configurationType}) not supported by Configuration Manager"),
};
return factory;
}
/// <summary>
/// Reads all keys from a section of an ini file.
/// </summary>
/// <param name="section"></param>
/// <returns></returns>
public override List<string> ReadAllKeys(string section)
{
return _configurationFile.ReadAllKeys(section);
}
/// <summary>
/// Returns a list of all of the sections in the ini file.
/// </summary>
/// <returns></returns>
public override List<string> ReadAllSections()
{
return _configurationFile.ReadAllSections();
}
/// <summary>
/// reads a list of values from configuration file
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="section"></param>
/// <param name="key"></param>
/// <param name="defList"></param>
/// <returns></returns>
public override List<T> ReadList<T>(string section, string key, IList<T> defList = null)
{
return _configurationFile.ReadList<T>(section, key, defList);
}
/// <summary>
/// reads a value from configuration file
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="section"></param>
/// <param name="key"></param>
/// <param name="defValue"></param>
/// <returns></returns>
public override T ReadValue<T>(string section, string key, T defValue = default)
{
return _configurationFile.ReadValue<T>(section, key, defValue);
}
/// <summary>
/// reads a single value in json format
/// </summary>
/// <param name="section"></param>
/// <param name="key"></param>
/// <returns>configuration value</returns>
/// <exception cref="NotImplementedException"></exception>
public override string ReadValue(string section, string key)
{
return _configurationFile.ReadValue(section, key);
}
/// <summary>
/// writes a list of values to configuration file
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="section"></param>
/// <param name="key"></param>
/// <param name="listToWrite"></param>
public override void WriteList<T>(string section, string key, IList<T> listToWrite)
{
_configurationFile.WriteList<T>(section, key, listToWrite);
}
/// <summary>
/// Write string value
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="section"></param>
/// <param name="key"></param>
/// <param name="lineToWrite"></param>
public override void WriteValue<T>(string section, string key, T lineToWrite)
{
_configurationFile.WriteValue(section, key, lineToWrite);
}
}
}

View File

@@ -0,0 +1,174 @@
// ******************************************************************************//
// RAYTHEON PROPRIETARY: THIS DOCUMENT CONTAINS DATA OR INFORMATION
// PROPRIETARY TO RAYTHEON COMPANY AND IS RESTRICTED TO USE ONLY BY PERSONS
// AUTHORIZED BY RAYTHEON COMPANY IN WRITING TO USE IT. DISCLOSURE TO
// UNAUTHORIZED PERSONS WOULD LIKELY CAUSE SUBSTANTIAL COMPETITIVE HARM TO
// RAYTHEON COMPANY''S BUSINESS POSITION. NEITHER SAID DOCUMENT NOR ITS
// CONTENTS SHALL BE FURNISHED OR DISCLOSED TO OR COPIED OR USED BY PERSONS
// OUTSIDE RAYTHEON COMPANY WITHOUT THE EXPRESS WRITTEN APPROVAL OF RAYTHEON
// COMPANY.
//
// THIS PROPRIETARY NOTICE IS NOT APPLICABLE IF DELIVERED TO THE U.S. GOVERNMENT
//
// UNPUBLISHED WORK - COPYRIGHT RAYTHEON COMPANY.
//
// WARNING: THIS DOCUMENT CONTAINS TECHNICAL DATA AND / OR TECHNOLOGY WHOSE
// EXPORT OR DISCLOSURE TO NON-U.S. PERSONS, WHEREVER LOCATED, IS RESTRICTED
// BY THE INTERNATIONAL TRAFFIC IN ARMS REGULATIONS (ITAR) (22 C.F.R. SECTION
// 120-130) OR THE EXPORT ADMINISTRATION REGULATIONS (EAR) (15 C.F.R. SECTION
// 730-774). THIS DOCUMENT CANNOT BE EXPORTED (E.G., PROVIDED TO A SUPPLIER
// OUTSIDE OF THE UNITED STATES) OR DISCLOSED TO A NON-U.S. PERSON, WHEREVER
// LOCATED, UNTIL A FINAL JURISDICTION AND CLASSIFICATION DETERMINATION HAS
// BEEN COMPLETED AND APPROVED BY RAYTHEON, AND ANY REQUIRED U.S. GOVERNMENT
// APPROVALS HAVE BEEN OBTAINED. VIOLATIONS ARE SUBJECT TO SEVERE CRIMINAL
// PENALTIES.
//
// DOD 5220.22-M, INDUSTRIAL SECURITY MANUAL, CHAPTER 5, SECTION 1 THROUGH 9 :
// FOR CLASSIFIED DOCUMENTS FOLLOW THE PROCEDURES IN OR DOD 5200.1-R,
// INFORMATION SECURITY PROGRAM, CHAPTER 6. FOR UNCLASSIFIED, LIMITED DOCUMENTS
// DESTROY BY ANY METHOD THAT WILL PREVENT DISCLOSURE OF CONTENTS OR
// RECONSTRUCTION OF THE DOCUMENT.
// ****************************************************************************//
using System;
using System.Collections.Generic;
using System.IO;
namespace Raytheon.Common
{
/// <summary>
///
/// </summary>
public abstract class ConfigurationFileBase : IConfigurationFile
{
/// <summary>
/// configuration file info
/// </summary>
protected static FileInfo _fileInfo;
/// <summary>
/// configuration file name
/// </summary>
protected string _fileName;
/// <summary>
/// returns file name
/// </summary>
public string FileName => _fileName;
/// <summary>
/// configuration type derived based on file extension
/// or by the type of the IConfigurationFile implementation
/// </summary>
protected ConfigurationFileType _configurationType;
/// <summary>
/// returns configuration type
/// </summary>
public ConfigurationFileType ConfigurationFileType => _configurationType;
/// <summary>
/// constructor that takes file name
/// </summary>
/// <param name="fileName"></param>
/// <exception cref="ArgumentException"></exception>
public ConfigurationFileBase(string fileName)
{
_fileInfo = new FileInfo(fileName);
_fileName = _fileInfo.FullName;
_configurationType = ConfigurationTypeFromFileExtension(_fileInfo.Extension);
}
/// <summary>
/// returns supported configuration type enum based on the file type
/// </summary>
/// <param name="fileExtension"></param>
/// <returns></returns>
protected static ConfigurationFileType ConfigurationTypeFromFileExtension(string fileExtension)
{
if (string.IsNullOrEmpty(fileExtension))
{
return ConfigurationFileType.OTHER;
}
return fileExtension.ToLower() switch
{
".ini" => ConfigurationFileType.INI,
".xml" => ConfigurationFileType.XML,
".json" => ConfigurationFileType.JSON,
".toml" => ConfigurationFileType.TOML,
".yaml" => ConfigurationFileType.YAML,
_ => ConfigurationFileType.OTHER,
};
}
/// <summary>
/// Reads all keys from a section of configuration file.
/// </summary>
/// <param name="section"></param>
/// <returns></returns>
public abstract List<string> ReadAllKeys(string section);
/// <summary>
/// Returns a list of all of the sections in the configuration file.
/// </summary>
/// <returns></returns>
public abstract List<string> ReadAllSections();
/// <summary>
/// reads a list of values from configuration file
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="section"></param>
/// <param name="key"></param>
/// <param name="defList"></param>
/// <returns></returns>
public abstract List<T> ReadList<T>(string section, string key, IList<T> defList = null);
/// <summary>
/// reads a single value from configuration file by section and key
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="section"></param>
/// <param name="key"></param>
/// <param name="defValue"></param>
/// <returns></returns>
public abstract T ReadValue<T>(string section, string key, T defValue = default);
/// <summary>
/// reads a single value from configuration file by section and key
/// </summary>
/// <param name="section"></param>
/// <param name="key"></param>
/// <returns></returns>
public abstract string ReadValue(string section, string key);
/// <summary>
/// writes a list of values to configuration file
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="section"></param>
/// <param name="key"></param>
/// <param name="listToWrite"></param>
public abstract void WriteList<T>(string section, string key, IList<T> listToWrite);
/// <summary>
/// Write a single value to a given section by key
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="section"></param>
/// <param name="key"></param>
/// <param name="lineToWrite"></param>
public abstract void WriteValue<T>(string section, string key, T lineToWrite);
/// <summary>
/// checks if the value exists in configuration file
/// </summary>
/// <param name="section"></param>
/// <param name="key"></param>
/// <returns></returns>
/// <exception cref="NotImplementedException"></exception>
virtual public bool ValueExists(string section, string key)
{
return ReadAllKeys(section).Contains(key);
}
}
}

View File

@@ -0,0 +1,472 @@
// ******************************************************************************//
// RAYTHEON PROPRIETARY: THIS DOCUMENT CONTAINS DATA OR INFORMATION
// PROPRIETARY TO RAYTHEON COMPANY AND IS RESTRICTED TO USE ONLY BY PERSONS
// AUTHORIZED BY RAYTHEON COMPANY IN WRITING TO USE IT. DISCLOSURE TO
// UNAUTHORIZED PERSONS WOULD LIKELY CAUSE SUBSTANTIAL COMPETITIVE HARM TO
// RAYTHEON COMPANY''S BUSINESS POSITION. NEITHER SAID DOCUMENT NOR ITS
// CONTENTS SHALL BE FURNISHED OR DISCLOSED TO OR COPIED OR USED BY PERSONS
// OUTSIDE RAYTHEON COMPANY WITHOUT THE EXPRESS WRITTEN APPROVAL OF RAYTHEON
// COMPANY.
//
// THIS PROPRIETARY NOTICE IS NOT APPLICABLE IF DELIVERED TO THE U.S. GOVERNMENT
//
// UNPUBLISHED WORK - COPYRIGHT RAYTHEON COMPANY.
//
// WARNING: THIS DOCUMENT CONTAINS TECHNICAL DATA AND / OR TECHNOLOGY WHOSE
// EXPORT OR DISCLOSURE TO NON-U.S. PERSONS, WHEREVER LOCATED, IS RESTRICTED
// BY THE INTERNATIONAL TRAFFIC IN ARMS REGULATIONS (ITAR) (22 C.F.R. SECTION
// 120-130) OR THE EXPORT ADMINISTRATION REGULATIONS (EAR) (15 C.F.R. SECTION
// 730-774). THIS DOCUMENT CANNOT BE EXPORTED (E.G., PROVIDED TO A SUPPLIER
// OUTSIDE OF THE UNITED STATES) OR DISCLOSED TO A NON-U.S. PERSON, WHEREVER
// LOCATED, UNTIL A FINAL JURISDICTION AND CLASSIFICATION DETERMINATION HAS
// BEEN COMPLETED AND APPROVED BY RAYTHEON, AND ANY REQUIRED U.S. GOVERNMENT
// APPROVALS HAVE BEEN OBTAINED. VIOLATIONS ARE SUBJECT TO SEVERE CRIMINAL
// PENALTIES.
//
// DOD 5220.22-M, INDUSTRIAL SECURITY MANUAL, CHAPTER 5, SECTION 1 THROUGH 9 :
// FOR CLASSIFIED DOCUMENTS FOLLOW THE PROCEDURES IN OR DOD 5200.1-R,
// INFORMATION SECURITY PROGRAM, CHAPTER 6. FOR UNCLASSIFIED, LIMITED DOCUMENTS
// DESTROY BY ANY METHOD THAT WILL PREVENT DISCLOSURE OF CONTENTS OR
// RECONSTRUCTION OF THE DOCUMENT.
// ****************************************************************************//
// Ignore Spelling: Deserialize
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
using System.Xml.Serialization;
using System.Xml.XPath;
namespace Raytheon.Common
{
/// <summary>
/// for serializing and deserializing class types
/// </summary>
internal static class XmlSerializerExtensions
{
/// <summary>
/// deserializes XML type into an object
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="value"></param>
/// <returns></returns>
public static T Deserialize<T>(this string value)
{
XmlSerializer serializer = new XmlSerializer(typeof(T));
using(StringReader reader = new StringReader(value))
{
return (T)serializer.Deserialize(reader);
}
}
/// <summary>
/// extension method to serialize XML type
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="value"></param>
/// <returns></returns>
public static string Serialize<T>(this T value)
{
if(value == null)
{
return string.Empty;
}
XmlSerializer xmlSerializer = new(typeof(T));
using(StringWriter stringWriter = new())
{
using(XmlWriter xmlWriter = XmlWriter.Create(stringWriter, new XmlWriterSettings { Indent = true }))
{
xmlSerializer.Serialize(xmlWriter, value);
return stringWriter.ToString();
}
}
}
/// <summary>
/// extension method to serialize XML type without a namespace
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="value"></param>
/// <returns></returns>
public static string SerializeNoNamespace<T>(this T value)
{
if(value == null)
{
return string.Empty;
}
XmlSerializerNamespaces emptyNamespaces = new(new[] { XmlQualifiedName.Empty });
XmlSerializer serializer = new(value.GetType());
XmlWriterSettings settings = new()
{
Indent = true,
OmitXmlDeclaration = true
};
using(StringWriter stream = new())
{
using(XmlWriter writer = XmlWriter.Create(stream, settings))
{
serializer.Serialize(writer, value, emptyNamespaces);
return stream.ToString();
}
}
}
}
/// <summary>
/// type conversion utility with a special case for enums
/// </summary>
public static class TypeConverter
{
/// <summary>
/// special rule for enumeration when converting a type
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="value"></param>
/// <returns></returns>
public static T ChangeType<T>(object value)
{
return typeof(T).IsEnum ? (T)Enum.Parse(typeof(T), value.ToString()) : (T)ChangeType(typeof(T), value);
}
/// <summary>
/// convert type with TypeDescriptor
/// </summary>
/// <param name="t"></param>
/// <param name="value"></param>
/// <returns></returns>
public static object ChangeType(Type t, object value)
{
System.ComponentModel.TypeConverter tc = TypeDescriptor.GetConverter(t);
return tc.ConvertFrom(value);
}
/// <summary>
/// register type with the type descriptor for later conversion
/// </summary>
/// <typeparam name="T"></typeparam>
/// <typeparam name="TC"></typeparam>
public static void RegisterTypeConverter<T, TC>() where TC : System.ComponentModel.TypeConverter
{
TypeDescriptor.AddAttributes(typeof(T), new TypeConverterAttribute(typeof(TC)));
}
}
/// <summary>
/// Helper class contains extension functions for reading types other than strings from configuration,
/// as well as reading lists of values
/// </summary>
public static class ConfigurationHelper
{
/// <summary>
/// template function for reading different types from configuration
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="configuration"></param>
/// <param name="section"></param>
/// <param name="key"></param>
/// <param name="defaultValue"></param>
/// <returns></returns>
public static T GetConfigurationValue<T>(this IConfiguration configuration, string section, string key, T defaultValue)
{
Type defaultType = typeof(T);
if(!defaultType.IsValueType && defaultType != typeof(string))
{
string tmpResult = configuration.GetConfigurationValue(section, key, string.Empty);
if(!string.IsNullOrEmpty(tmpResult))
{
return tmpResult.Deserialize<T>();
}
else
{
configuration.SetConfigurationValue(section, key, defaultValue);
return defaultValue;
}
}
else
{
string tmpResult = configuration.GetConfigurationValue(section, key, defaultValue.ToString());
return !string.IsNullOrEmpty(tmpResult) ? TypeConverter.ChangeType<T>(tmpResult) : default;
}
}
/// <summary>
/// Sets configuration value.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="configuration"></param>
/// <param name="section"></param>
/// <param name="key"></param>
/// <param name="valueToWrite"></param>
public static void SetConfigurationValue<T>(this IConfiguration configuration, string section, string key, T valueToWrite)
{
Type defaultType = typeof(T);
if(!defaultType.IsValueType && defaultType != typeof(string))
{
configuration.SetConfigurationValue(section, key, valueToWrite.SerializeNoNamespace());
}
else
{
configuration.SetConfigurationValue(section, key, valueToWrite.ToString());
}
}
/// <summary>
/// returns multi-value result (list of T) from configuration
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="configuration"></param>
/// <param name="section"></param>
/// <param name="key"></param>
/// <param name="defaultValue"></param>
/// <returns></returns>
public static List<T> GetConfigurationListValue<T>(this IConfiguration configuration, string section, string key, IList<T> defaultValue)
{
string tmpResult = configuration.GetXmlConfiguration(section);
if(string.IsNullOrEmpty(tmpResult) || !ContainsSection(tmpResult, key))
{
SetConfigurationListValue(configuration, section, key, defaultValue);
return new List<T>(defaultValue);
}
else
{
var stringRes = BuildElementListFromXml(tmpResult, key);
XmlSerializer xmlSerializer = new XmlSerializer(typeof(T));
List<T> result = new List<T>();
foreach(string item in stringRes)
{
if(string.IsNullOrEmpty(item))
{
continue;
}
if(item.TrimStart().StartsWith("<"))
{
result.Add(item.Deserialize<T>());
}
else
{
result.Add(TypeConverter.ChangeType<T>(item));
}
}
return result;
}
}
/// <summary>
/// Writes configuration list of values.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="configuration"></param>
/// <param name="section"></param>
/// <param name="key"></param>
/// <param name="listToWrite"></param>
public static void SetConfigurationListValue<T>(this IConfiguration configuration, string section, string key, IList<T> listToWrite)
{
StringBuilder xmlStr = new();
string data = configuration.GetXmlConfiguration(section);
if(ContainsSection(data, $"{key}s"))
{
xmlStr.Append($"<{key}s>");
foreach(var item in listToWrite)
{
xmlStr.Append($"<{key}>");
xmlStr.Append(item.ToString());
xmlStr.Append($"</{key}>");
}
xmlStr.Append($"</{key}s>");
configuration.SetXmlConfiguration(section, xmlStr.ToString());
}
else
{
xmlStr.Append($"<{key}>");
foreach(var item in listToWrite)
{
xmlStr.Append(item.SerializeNoNamespace());
}
xmlStr.Append($"</{key}>");
XElement xElement = new XElement(key, XElement.Parse(xmlStr.ToString()));
if(string.IsNullOrEmpty(data))
{
data = $"<XmlConfiguration name=\"{section}\"></XmlConfiguration>";
}
XDocument doc = XDocument.Parse(data);
XElement existing = doc.Descendants(key).FirstOrDefault();
if(existing != null)
{
existing.ReplaceWith(xElement);
var reader = doc.CreateReader();
reader.MoveToContent();
string innerXml = reader.ReadInnerXml();
configuration.SetXmlConfiguration(section, innerXml);
}
else
{
doc.Root.Add(xElement.FirstNode);
var reader = doc.CreateReader();
reader.MoveToContent();
string outerXml = reader.ReadOuterXml();
configuration.SetXmlConfiguration(section, outerXml);
}
}
}
/// <summary>
/// returns values from XML section converted to string list
/// </summary>
/// <param name="data"></param>
/// <param name="key"></param>
/// <returns></returns>
private static List<string> BuildElementListFromXml(string data, string key)
{
XElement doc = XElement.Parse(data);
IEnumerable<XElement> xmlMessages;
if(ContainsSection(data, $"{key}s"))
{
xmlMessages = from m in doc.Elements($"{key}s").Elements(key)
select m;
var messages = xmlMessages.Select(x => x.Value);
return messages?.ToList();
}
else
{
xmlMessages = from m in doc.Elements($"{key}").Elements()
select m;
List<string> result = new();
foreach(var item in xmlMessages)
{
var reader = item.CreateReader();
reader.MoveToContent();
result.Add(reader.ReadOuterXml());
}
return result;
}
}
private static bool ContainsSection(string xmlString, string sectionName)
{
if(string.IsNullOrEmpty(xmlString))
{
return false;
}
try
{
XDocument doc = XDocument.Parse(xmlString);
return doc.Descendants(sectionName).Any();
}
catch
{
return false;
}
}
/// <summary>
/// From XML configuration file reads all sections under IniConfiguration root
/// </summary>
/// <returns></returns>
public static List<string> GetAvailableConfigSections(string fileName)
{
List<string> sections = new();
FileInfo fileInfo = new(fileName);
if(!fileInfo.Exists)
{
return null;
}
XDocument xdocument = XDocument.Load(fileInfo.FullName);
if(xdocument != null)
{
var configurationSection = xdocument.Root.Element("IniConfiguration");
if(configurationSection != null && configurationSection.HasElements)
{
var sectionElements = configurationSection.Elements();
sections.AddRange(from item in sectionElements
let name = item?.FirstAttribute?.Value
where !string.IsNullOrEmpty(name)
select name);
}
configurationSection = xdocument.Root.Element("XmlConfigurations");
if(configurationSection != null && configurationSection.HasElements)
{
var sectionElements = configurationSection.Elements();
sections.AddRange(from item in sectionElements
let name = item?.FirstAttribute?.Value
where !string.IsNullOrEmpty(name)
select name);
}
}
return sections;
}
/// <summary>
/// From XML configuration file reads all keys from config sections under IniConfiguration root
/// </summary>
/// <returns></returns>
public static List<string> GetAvailableConfigSectionKeys(string fileName, string sectionName)
{
List<string> sections = new();
FileInfo fileInfo = new(fileName);
if(!fileInfo.Exists)
{
return null;
}
XDocument xdocument = XDocument.Load(fileInfo.FullName);
if(xdocument != null)
{
var configurationSection = xdocument.XPathSelectElement($"//IniConfiguration//section[@name='{sectionName}']");
if(configurationSection != null && configurationSection.HasElements)
{
var sectionElements = configurationSection.Elements();
sections.AddRange(from item in sectionElements
let name = item?.FirstAttribute?.Value
where !string.IsNullOrEmpty(name)
select name);
}
configurationSection = xdocument.XPathSelectElement($"//XmlConfigurations//XmlConfiguration[@name='{sectionName}']");
if(configurationSection != null && configurationSection.HasElements)
{
var sectionElements = configurationSection.Elements();
sections.AddRange(from item in sectionElements
let name = item?.Name
where name != null
select name.ToString());
}
}
return sections;
}
}
}

View File

@@ -0,0 +1,72 @@
// ******************************************************************************//
// RAYTHEON PROPRIETARY: THIS DOCUMENT CONTAINS DATA OR INFORMATION
// PROPRIETARY TO RAYTHEON COMPANY AND IS RESTRICTED TO USE ONLY BY PERSONS
// AUTHORIZED BY RAYTHEON COMPANY IN WRITING TO USE IT. DISCLOSURE TO
// UNAUTHORIZED PERSONS WOULD LIKELY CAUSE SUBSTANTIAL COMPETITIVE HARM TO
// RAYTHEON COMPANY''S BUSINESS POSITION. NEITHER SAID DOCUMENT NOR ITS
// CONTENTS SHALL BE FURNISHED OR DISCLOSED TO OR COPIED OR USED BY PERSONS
// OUTSIDE RAYTHEON COMPANY WITHOUT THE EXPRESS WRITTEN APPROVAL OF RAYTHEON
// COMPANY.
//
// THIS PROPRIETARY NOTICE IS NOT APPLICABLE IF DELIVERED TO THE U.S. GOVERNMENT
//
// UNPUBLISHED WORK - COPYRIGHT RAYTHEON COMPANY.
//
// WARNING: THIS DOCUMENT CONTAINS TECHNICAL DATA AND / OR TECHNOLOGY WHOSE
// EXPORT OR DISCLOSURE TO NON-U.S. PERSONS, WHEREVER LOCATED, IS RESTRICTED
// BY THE INTERNATIONAL TRAFFIC IN ARMS REGULATIONS (ITAR) (22 C.F.R. SECTION
// 120-130) OR THE EXPORT ADMINISTRATION REGULATIONS (EAR) (15 C.F.R. SECTION
// 730-774). THIS DOCUMENT CANNOT BE EXPORTED (E.G., PROVIDED TO A SUPPLIER
// OUTSIDE OF THE UNITED STATES) OR DISCLOSED TO A NON-U.S. PERSON, WHEREVER
// LOCATED, UNTIL A FINAL JURISDICTION AND CLASSIFICATION DETERMINATION HAS
// BEEN COMPLETED AND APPROVED BY RAYTHEON, AND ANY REQUIRED U.S. GOVERNMENT
// APPROVALS HAVE BEEN OBTAINED. VIOLATIONS ARE SUBJECT TO SEVERE CRIMINAL
// PENALTIES.
//
// DOD 5220.22-M, INDUSTRIAL SECURITY MANUAL, CHAPTER 5, SECTION 1 THROUGH 9 :
// FOR CLASSIFIED DOCUMENTS FOLLOW THE PROCEDURES IN OR DOD 5200.1-R,
// INFORMATION SECURITY PROGRAM, CHAPTER 6. FOR UNCLASSIFIED, LIMITED DOCUMENTS
// DESTROY BY ANY METHOD THAT WILL PREVENT DISCLOSURE OF CONTENTS OR
// RECONSTRUCTION OF THE DOCUMENT.
// ****************************************************************************//
using System;
namespace Raytheon.Common
{
/// <summary>
/// Generic configuration factory based on the type
/// </summary>
public class ConfigurationFileFactory : ConfigurationFileFactoryBase
{
private readonly string _type;
/// <summary>
///
/// </summary>
/// <param name="type"></param>
public ConfigurationFileFactory(string type)
{
_type = type;
}
/// <summary>
///
/// </summary>
/// <param name="fileName"></param>
/// <returns></returns>
/// <exception cref="InvalidOperationException"></exception>
public override IConfigurationFile CreateConfigurationFile(string fileName)
{
Type type = Type.GetType(_type);
if (type == null)
{
throw new InvalidOperationException($"File format not supported with {_type} package.");
}
else
{
return (IConfigurationFile)Activator.CreateInstance(type, fileName);
}
}
}
}

View File

@@ -0,0 +1,59 @@
// ******************************************************************************//
// RAYTHEON PROPRIETARY: THIS DOCUMENT CONTAINS DATA OR INFORMATION
// PROPRIETARY TO RAYTHEON COMPANY AND IS RESTRICTED TO USE ONLY BY PERSONS
// AUTHORIZED BY RAYTHEON COMPANY IN WRITING TO USE IT. DISCLOSURE TO
// UNAUTHORIZED PERSONS WOULD LIKELY CAUSE SUBSTANTIAL COMPETITIVE HARM TO
// RAYTHEON COMPANY''S BUSINESS POSITION. NEITHER SAID DOCUMENT NOR ITS
// CONTENTS SHALL BE FURNISHED OR DISCLOSED TO OR COPIED OR USED BY PERSONS
// OUTSIDE RAYTHEON COMPANY WITHOUT THE EXPRESS WRITTEN APPROVAL OF RAYTHEON
// COMPANY.
//
// THIS PROPRIETARY NOTICE IS NOT APPLICABLE IF DELIVERED TO THE U.S. GOVERNMENT
//
// UNPUBLISHED WORK - COPYRIGHT RAYTHEON COMPANY.
//
// WARNING: THIS DOCUMENT CONTAINS TECHNICAL DATA AND / OR TECHNOLOGY WHOSE
// EXPORT OR DISCLOSURE TO NON-U.S. PERSONS, WHEREVER LOCATED, IS RESTRICTED
// BY THE INTERNATIONAL TRAFFIC IN ARMS REGULATIONS (ITAR) (22 C.F.R. SECTION
// 120-130) OR THE EXPORT ADMINISTRATION REGULATIONS (EAR) (15 C.F.R. SECTION
// 730-774). THIS DOCUMENT CANNOT BE EXPORTED (E.G., PROVIDED TO A SUPPLIER
// OUTSIDE OF THE UNITED STATES) OR DISCLOSED TO A NON-U.S. PERSON, WHEREVER
// LOCATED, UNTIL A FINAL JURISDICTION AND CLASSIFICATION DETERMINATION HAS
// BEEN COMPLETED AND APPROVED BY RAYTHEON, AND ANY REQUIRED U.S. GOVERNMENT
// APPROVALS HAVE BEEN OBTAINED. VIOLATIONS ARE SUBJECT TO SEVERE CRIMINAL
// PENALTIES.
//
// DOD 5220.22-M, INDUSTRIAL SECURITY MANUAL, CHAPTER 5, SECTION 1 THROUGH 9 :
// FOR CLASSIFIED DOCUMENTS FOLLOW THE PROCEDURES IN OR DOD 5200.1-R,
// INFORMATION SECURITY PROGRAM, CHAPTER 6. FOR UNCLASSIFIED, LIMITED DOCUMENTS
// DESTROY BY ANY METHOD THAT WILL PREVENT DISCLOSURE OF CONTENTS OR
// RECONSTRUCTION OF THE DOCUMENT.
// ****************************************************************************//
namespace Raytheon.Common
{
/// <summary>
/// Configuration file factory base class for the Factory Method pattern
/// </summary>
public abstract class ConfigurationFileFactoryBase
{
/// <summary>
/// template method for creating configuration file
/// </summary>
/// <param name="fileName"></param>
/// <returns></returns>
public abstract IConfigurationFile CreateConfigurationFile(string fileName);
/// <summary>
/// creates configuration file based on the overwrite of the
/// concrete implementation of the CreateConfigurationFile method
/// </summary>
/// <param name="fileName"></param>
/// <returns></returns>
public IConfigurationFile GetConfigurationFile(string fileName)
{
IConfigurationFile configurationFile = CreateConfigurationFile(fileName);
return configurationFile;
}
}
}

View File

@@ -0,0 +1,50 @@
// ******************************************************************************//
// RAYTHEON PROPRIETARY: THIS DOCUMENT CONTAINS DATA OR INFORMATION
// PROPRIETARY TO RAYTHEON COMPANY AND IS RESTRICTED TO USE ONLY BY PERSONS
// AUTHORIZED BY RAYTHEON COMPANY IN WRITING TO USE IT. DISCLOSURE TO
// UNAUTHORIZED PERSONS WOULD LIKELY CAUSE SUBSTANTIAL COMPETITIVE HARM TO
// RAYTHEON COMPANY''S BUSINESS POSITION. NEITHER SAID DOCUMENT NOR ITS
// CONTENTS SHALL BE FURNISHED OR DISCLOSED TO OR COPIED OR USED BY PERSONS
// OUTSIDE RAYTHEON COMPANY WITHOUT THE EXPRESS WRITTEN APPROVAL OF RAYTHEON
// COMPANY.
//
// THIS PROPRIETARY NOTICE IS NOT APPLICABLE IF DELIVERED TO THE U.S. GOVERNMENT
//
// UNPUBLISHED WORK - COPYRIGHT RAYTHEON COMPANY.
//
// WARNING: THIS DOCUMENT CONTAINS TECHNICAL DATA AND / OR TECHNOLOGY WHOSE
// EXPORT OR DISCLOSURE TO NON-U.S. PERSONS, WHEREVER LOCATED, IS RESTRICTED
// BY THE INTERNATIONAL TRAFFIC IN ARMS REGULATIONS (ITAR) (22 C.F.R. SECTION
// 120-130) OR THE EXPORT ADMINISTRATION REGULATIONS (EAR) (15 C.F.R. SECTION
// 730-774). THIS DOCUMENT CANNOT BE EXPORTED (E.G., PROVIDED TO A SUPPLIER
// OUTSIDE OF THE UNITED STATES) OR DISCLOSED TO A NON-U.S. PERSON, WHEREVER
// LOCATED, UNTIL A FINAL JURISDICTION AND CLASSIFICATION DETERMINATION HAS
// BEEN COMPLETED AND APPROVED BY RAYTHEON, AND ANY REQUIRED U.S. GOVERNMENT
// APPROVALS HAVE BEEN OBTAINED. VIOLATIONS ARE SUBJECT TO SEVERE CRIMINAL
// PENALTIES.
//
// DOD 5220.22-M, INDUSTRIAL SECURITY MANUAL, CHAPTER 5, SECTION 1 THROUGH 9 :
// FOR CLASSIFIED DOCUMENTS FOLLOW THE PROCEDURES IN OR DOD 5200.1-R,
// INFORMATION SECURITY PROGRAM, CHAPTER 6. FOR UNCLASSIFIED, LIMITED DOCUMENTS
// DESTROY BY ANY METHOD THAT WILL PREVENT DISCLOSURE OF CONTENTS OR
// RECONSTRUCTION OF THE DOCUMENT.
// ****************************************************************************//
namespace Raytheon.Common
{
/// <summary>
/// IniConfigurationFile factory class
/// </summary>
public class IniConfigurationFileFactory : ConfigurationFileFactoryBase
{
/// <summary>
/// IniConfigurationFile factory method
/// </summary>
/// <param name="fileName"></param>
/// <returns></returns>
public override IConfigurationFile CreateConfigurationFile(string fileName)
{
return new IniConfigurationFile(fileName);
}
}
}

View File

@@ -0,0 +1,61 @@
// ******************************************************************************//
// RAYTHEON PROPRIETARY: THIS DOCUMENT CONTAINS DATA OR INFORMATION
// PROPRIETARY TO RAYTHEON COMPANY AND IS RESTRICTED TO USE ONLY BY PERSONS
// AUTHORIZED BY RAYTHEON COMPANY IN WRITING TO USE IT. DISCLOSURE TO
// UNAUTHORIZED PERSONS WOULD LIKELY CAUSE SUBSTANTIAL COMPETITIVE HARM TO
// RAYTHEON COMPANY''S BUSINESS POSITION. NEITHER SAID DOCUMENT NOR ITS
// CONTENTS SHALL BE FURNISHED OR DISCLOSED TO OR COPIED OR USED BY PERSONS
// OUTSIDE RAYTHEON COMPANY WITHOUT THE EXPRESS WRITTEN APPROVAL OF RAYTHEON
// COMPANY.
//
// THIS PROPRIETARY NOTICE IS NOT APPLICABLE IF DELIVERED TO THE U.S. GOVERNMENT
//
// UNPUBLISHED WORK - COPYRIGHT RAYTHEON COMPANY.
//
// WARNING: THIS DOCUMENT CONTAINS TECHNICAL DATA AND / OR TECHNOLOGY WHOSE
// EXPORT OR DISCLOSURE TO NON-U.S. PERSONS, WHEREVER LOCATED, IS RESTRICTED
// BY THE INTERNATIONAL TRAFFIC IN ARMS REGULATIONS (ITAR) (22 C.F.R. SECTION
// 120-130) OR THE EXPORT ADMINISTRATION REGULATIONS (EAR) (15 C.F.R. SECTION
// 730-774). THIS DOCUMENT CANNOT BE EXPORTED (E.G., PROVIDED TO A SUPPLIER
// OUTSIDE OF THE UNITED STATES) OR DISCLOSED TO A NON-U.S. PERSON, WHEREVER
// LOCATED, UNTIL A FINAL JURISDICTION AND CLASSIFICATION DETERMINATION HAS
// BEEN COMPLETED AND APPROVED BY RAYTHEON, AND ANY REQUIRED U.S. GOVERNMENT
// APPROVALS HAVE BEEN OBTAINED. VIOLATIONS ARE SUBJECT TO SEVERE CRIMINAL
// PENALTIES.
//
// DOD 5220.22-M, INDUSTRIAL SECURITY MANUAL, CHAPTER 5, SECTION 1 THROUGH 9 :
// FOR CLASSIFIED DOCUMENTS FOLLOW THE PROCEDURES IN OR DOD 5200.1-R,
// INFORMATION SECURITY PROGRAM, CHAPTER 6. FOR UNCLASSIFIED, LIMITED DOCUMENTS
// DESTROY BY ANY METHOD THAT WILL PREVENT DISCLOSURE OF CONTENTS OR
// RECONSTRUCTION OF THE DOCUMENT.
// ****************************************************************************//
using System;
namespace Raytheon.Common
{
/// <summary>
/// JsonConfigurationFile factory class
/// </summary>
public class JsonConfigurationFileFactory : ConfigurationFileFactoryBase
{
/// <summary>
/// JsonConfigurationFile factory method
/// </summary>
/// <param name="fileName"></param>
/// <returns></returns>
/// <exception cref="InvalidOperationException"></exception>
public override IConfigurationFile CreateConfigurationFile(string fileName)
{
Type jsonType = Type.GetType("Raytheon.Common.JsonConfigurationFile, Raytheon.Configuration.Json");
if (jsonType == null)
{
throw new InvalidOperationException($"JSON file format supported with Raytheon.Configuration.Json package.");
}
else
{
return (IConfigurationFile)Activator.CreateInstance(jsonType, fileName);
}
}
}
}

View File

@@ -0,0 +1,60 @@
// ******************************************************************************//
// RAYTHEON PROPRIETARY: THIS DOCUMENT CONTAINS DATA OR INFORMATION
// PROPRIETARY TO RAYTHEON COMPANY AND IS RESTRICTED TO USE ONLY BY PERSONS
// AUTHORIZED BY RAYTHEON COMPANY IN WRITING TO USE IT. DISCLOSURE TO
// UNAUTHORIZED PERSONS WOULD LIKELY CAUSE SUBSTANTIAL COMPETITIVE HARM TO
// RAYTHEON COMPANY''S BUSINESS POSITION. NEITHER SAID DOCUMENT NOR ITS
// CONTENTS SHALL BE FURNISHED OR DISCLOSED TO OR COPIED OR USED BY PERSONS
// OUTSIDE RAYTHEON COMPANY WITHOUT THE EXPRESS WRITTEN APPROVAL OF RAYTHEON
// COMPANY.
//
// THIS PROPRIETARY NOTICE IS NOT APPLICABLE IF DELIVERED TO THE U.S. GOVERNMENT
//
// UNPUBLISHED WORK - COPYRIGHT RAYTHEON COMPANY.
//
// WARNING: THIS DOCUMENT CONTAINS TECHNICAL DATA AND / OR TECHNOLOGY WHOSE
// EXPORT OR DISCLOSURE TO NON-U.S. PERSONS, WHEREVER LOCATED, IS RESTRICTED
// BY THE INTERNATIONAL TRAFFIC IN ARMS REGULATIONS (ITAR) (22 C.F.R. SECTION
// 120-130) OR THE EXPORT ADMINISTRATION REGULATIONS (EAR) (15 C.F.R. SECTION
// 730-774). THIS DOCUMENT CANNOT BE EXPORTED (E.G., PROVIDED TO A SUPPLIER
// OUTSIDE OF THE UNITED STATES) OR DISCLOSED TO A NON-U.S. PERSON, WHEREVER
// LOCATED, UNTIL A FINAL JURISDICTION AND CLASSIFICATION DETERMINATION HAS
// BEEN COMPLETED AND APPROVED BY RAYTHEON, AND ANY REQUIRED U.S. GOVERNMENT
// APPROVALS HAVE BEEN OBTAINED. VIOLATIONS ARE SUBJECT TO SEVERE CRIMINAL
// PENALTIES.
//
// DOD 5220.22-M, INDUSTRIAL SECURITY MANUAL, CHAPTER 5, SECTION 1 THROUGH 9 :
// FOR CLASSIFIED DOCUMENTS FOLLOW THE PROCEDURES IN OR DOD 5200.1-R,
// INFORMATION SECURITY PROGRAM, CHAPTER 6. FOR UNCLASSIFIED, LIMITED DOCUMENTS
// DESTROY BY ANY METHOD THAT WILL PREVENT DISCLOSURE OF CONTENTS OR
// RECONSTRUCTION OF THE DOCUMENT.
// ****************************************************************************//
using System;
namespace Raytheon.Common
{
/// <summary>
/// TomlConfigurationFile factory class
/// </summary>
public class TomlConfigurationFileFactory : ConfigurationFileFactoryBase
{
/// <summary>
/// TomlConfigurationFile factory method
/// </summary>
/// <param name="fileName"></param>
/// <returns></returns>
/// <exception cref="InvalidOperationException"></exception>
public override IConfigurationFile CreateConfigurationFile(string fileName)
{
Type tomlType = Type.GetType("Raytheon.Common.TomlConfigurationFile, Raytheon.Configuration.Toml");
if (tomlType == null)
{
throw new InvalidOperationException($"TOML file format supported with Raytheon.Configuration.Toml package.");
}
else
{
return (IConfigurationFile)Activator.CreateInstance(tomlType, fileName);
}
}
}
}

View File

@@ -0,0 +1,50 @@
// ******************************************************************************//
// RAYTHEON PROPRIETARY: THIS DOCUMENT CONTAINS DATA OR INFORMATION
// PROPRIETARY TO RAYTHEON COMPANY AND IS RESTRICTED TO USE ONLY BY PERSONS
// AUTHORIZED BY RAYTHEON COMPANY IN WRITING TO USE IT. DISCLOSURE TO
// UNAUTHORIZED PERSONS WOULD LIKELY CAUSE SUBSTANTIAL COMPETITIVE HARM TO
// RAYTHEON COMPANY''S BUSINESS POSITION. NEITHER SAID DOCUMENT NOR ITS
// CONTENTS SHALL BE FURNISHED OR DISCLOSED TO OR COPIED OR USED BY PERSONS
// OUTSIDE RAYTHEON COMPANY WITHOUT THE EXPRESS WRITTEN APPROVAL OF RAYTHEON
// COMPANY.
//
// THIS PROPRIETARY NOTICE IS NOT APPLICABLE IF DELIVERED TO THE U.S. GOVERNMENT
//
// UNPUBLISHED WORK - COPYRIGHT RAYTHEON COMPANY.
//
// WARNING: THIS DOCUMENT CONTAINS TECHNICAL DATA AND / OR TECHNOLOGY WHOSE
// EXPORT OR DISCLOSURE TO NON-U.S. PERSONS, WHEREVER LOCATED, IS RESTRICTED
// BY THE INTERNATIONAL TRAFFIC IN ARMS REGULATIONS (ITAR) (22 C.F.R. SECTION
// 120-130) OR THE EXPORT ADMINISTRATION REGULATIONS (EAR) (15 C.F.R. SECTION
// 730-774). THIS DOCUMENT CANNOT BE EXPORTED (E.G., PROVIDED TO A SUPPLIER
// OUTSIDE OF THE UNITED STATES) OR DISCLOSED TO A NON-U.S. PERSON, WHEREVER
// LOCATED, UNTIL A FINAL JURISDICTION AND CLASSIFICATION DETERMINATION HAS
// BEEN COMPLETED AND APPROVED BY RAYTHEON, AND ANY REQUIRED U.S. GOVERNMENT
// APPROVALS HAVE BEEN OBTAINED. VIOLATIONS ARE SUBJECT TO SEVERE CRIMINAL
// PENALTIES.
//
// DOD 5220.22-M, INDUSTRIAL SECURITY MANUAL, CHAPTER 5, SECTION 1 THROUGH 9 :
// FOR CLASSIFIED DOCUMENTS FOLLOW THE PROCEDURES IN OR DOD 5200.1-R,
// INFORMATION SECURITY PROGRAM, CHAPTER 6. FOR UNCLASSIFIED, LIMITED DOCUMENTS
// DESTROY BY ANY METHOD THAT WILL PREVENT DISCLOSURE OF CONTENTS OR
// RECONSTRUCTION OF THE DOCUMENT.
// ****************************************************************************//
namespace Raytheon.Common
{
/// <summary>
/// XmlConfigurationFile factory class
/// </summary>
public class XmlConfigurationFileFactory : ConfigurationFileFactoryBase
{
/// <summary>
/// XmlConfigurationFile factory method
/// </summary>
/// <param name="fileName"></param>
/// <returns></returns>
public override IConfigurationFile CreateConfigurationFile(string fileName)
{
return new XmlConfigurationFile(fileName);
}
}
}

View File

@@ -0,0 +1,261 @@
// ******************************************************************************//
// RAYTHEON PROPRIETARY: THIS DOCUMENT CONTAINS DATA OR INFORMATION
// PROPRIETARY TO RAYTHEON COMPANY AND IS RESTRICTED TO USE ONLY BY PERSONS
// AUTHORIZED BY RAYTHEON COMPANY IN WRITING TO USE IT. DISCLOSURE TO
// UNAUTHORIZED PERSONS WOULD LIKELY CAUSE SUBSTANTIAL COMPETITIVE HARM TO
// RAYTHEON COMPANY''S BUSINESS POSITION. NEITHER SAID DOCUMENT NOR ITS
// CONTENTS SHALL BE FURNISHED OR DISCLOSED TO OR COPIED OR USED BY PERSONS
// OUTSIDE RAYTHEON COMPANY WITHOUT THE EXPRESS WRITTEN APPROVAL OF RAYTHEON
// COMPANY.
//
// THIS PROPRIETARY NOTICE IS NOT APPLICABLE IF DELIVERED TO THE U.S. GOVERNMENT
//
// UNPUBLISHED WORK - COPYRIGHT RAYTHEON COMPANY.
//
// WARNING: THIS DOCUMENT CONTAINS TECHNICAL DATA AND / OR TECHNOLOGY WHOSE
// EXPORT OR DISCLOSURE TO NON-U.S. PERSONS, WHEREVER LOCATED, IS RESTRICTED
// BY THE INTERNATIONAL TRAFFIC IN ARMS REGULATIONS (ITAR) (22 C.F.R. SECTION
// 120-130) OR THE EXPORT ADMINISTRATION REGULATIONS (EAR) (15 C.F.R. SECTION
// 730-774). THIS DOCUMENT CANNOT BE EXPORTED (E.G., PROVIDED TO A SUPPLIER
// OUTSIDE OF THE UNITED STATES) OR DISCLOSED TO A NON-U.S. PERSON, WHEREVER
// LOCATED, UNTIL A FINAL JURISDICTION AND CLASSIFICATION DETERMINATION HAS
// BEEN COMPLETED AND APPROVED BY RAYTHEON, AND ANY REQUIRED U.S. GOVERNMENT
// APPROVALS HAVE BEEN OBTAINED. VIOLATIONS ARE SUBJECT TO SEVERE CRIMINAL
// PENALTIES.
//
// DOD 5220.22-M, INDUSTRIAL SECURITY MANUAL, CHAPTER 5, SECTION 1 THROUGH 9 :
// FOR CLASSIFIED DOCUMENTS FOLLOW THE PROCEDURES IN OR DOD 5200.1-R,
// INFORMATION SECURITY PROGRAM, CHAPTER 6. FOR UNCLASSIFIED, LIMITED DOCUMENTS
// DESTROY BY ANY METHOD THAT WILL PREVENT DISCLOSURE OF CONTENTS OR
// RECONSTRUCTION OF THE DOCUMENT.
// ****************************************************************************//
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
namespace Raytheon.Common
{
/// <summary>
/// Read/Write to an ini file.
/// </summary>
public class IniConfigurationFile : ConfigurationFileBase
{
#region PrivateMemberVariables
internal static class NativeMethods
{
[DllImport("kernel32.dll", CharSet = CharSet.Unicode)]
internal static extern int GetPrivateProfileString(string lpAppName, string lpKeyName, string lpDefault, string lpReturnedstring, int nSize, string lpFileName);
[DllImport("kernel32.dll", CharSet = CharSet.Unicode)]
[return: MarshalAs(UnmanagedType.Bool)]
internal static extern bool WritePrivateProfileString(string lpAppName, string lpKeyName, string line, string lpFileName);
[DllImport("kernel32.dll", CharSet = CharSet.Unicode)]
[return: MarshalAs(UnmanagedType.Bool)]
internal static extern bool WritePrivateProfileSection(string lpAppName, string line, string lpFileName);
[DllImport("kernel32.dll", CharSet = CharSet.Unicode)]
internal static extern int GetPrivateProfileSectionNames(byte[] sections, int bufferSize, string filename);
}
#endregion
/// <summary>
/// The constructor. It will check to make sure the file exists and throw an exception it if does not
/// </summary>
/// <param name="fileName">The ini file name (path).</param>
public IniConfigurationFile(string fileName)
: base(fileName)
{
if (ConfigurationFileType != ConfigurationFileType.INI)
{
throw new ArgumentException("Expecting INI file configuration type");
}
if (!_fileInfo.Exists)
{
throw new Exception($"Can't find file: {fileName}");
}
}
#region PublicFunctions
/// <summary>
/// reads a value from configuration file
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="section"></param>
/// <param name="key"></param>
/// <param name="defaultValue"></param>
/// <returns></returns>
public override T ReadValue<T>(string section, string key, T defaultValue = default)
{
const int BUFFER_SIZE = 1024;
string temp = new string('\0', BUFFER_SIZE);
int numBytes = NativeMethods.GetPrivateProfileString(section, key, "", temp, BUFFER_SIZE, _fileName);
if (numBytes == 0)
{
WriteValue<T>(section, key, defaultValue);
return defaultValue;
}
else
{
temp = temp.TrimEnd('\0');
return TypeConverter.ChangeType<T>(temp);
}
}
/// <summary>
/// reads a value from configuration file
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="section"></param>
/// <param name="key"></param>
/// <param name="defaultValue"></param>
/// <returns></returns>
public override string ReadValue(string section, string key)
{
const int BUFFER_SIZE = 1024;
string temp = new string('\0', BUFFER_SIZE);
if (!ReadAllSections().Contains(section))
throw new Exception($"Section '{section}' doesn't exist in {_fileName}");
if (!ReadAllKeys(section).Contains(key))
throw new Exception($"Key '{key}' doesn't exist under section '{section}' in {_fileName}");
int numBytes = NativeMethods.GetPrivateProfileString(section, key, "", temp, BUFFER_SIZE, _fileName);
if (numBytes > 0)
{
return temp.TrimEnd('\0');
}
else
{
throw new Exception($"The value associated with key '{key}' under section '{section}' is empty in {_fileName}");
}
}
/// <summary>
/// Write string value
/// </summary>
/// <param name="section"></param>
/// <param name="key"></param>
/// <param name="lineToWrite"></param>
public override void WriteValue<T>(string section, string key, T lineToWrite)
{
if (!NativeMethods.WritePrivateProfileString(section, key, $"{lineToWrite}", _fileName))
{
throw new Exception($"IniFile::WriteValue() - WritePrivateProfileString returned false for section: {section}, key {key}, line {lineToWrite}");
}
}
/// <summary>
/// reads a list of values from INI configuration file
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="section"></param>
/// <param name="key"></param>
/// <param name="defaultList"></param>
/// <returns></returns>
public override List<T> ReadList<T>(string section, string key, IList<T> defaultList = null)
{
List<T> resultList = new();
string stringResult = ReadValue(section, key, string.Empty);
if (string.IsNullOrEmpty(stringResult))
{
WriteList(section, key, defaultList);
return new List<T>(defaultList);
}
foreach (string item in stringResult.Split('|'))
{
resultList.Add(TypeConverter.ChangeType<T>(item));
}
return resultList;
}
/// <summary>
/// writes a list of values to INI configuration file
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="section"></param>
/// <param name="key"></param>
/// <param name="listToWrite"></param>
public override void WriteList<T>(string section, string key, IList<T> listToWrite)
{
List<string> stringListToWrite = new(listToWrite.Select(a => a.ToString()));
WriteValue(section, key, string.Join("|", stringListToWrite));
}
/// <summary>
/// Reads all keys from a section of an ini file.
/// </summary>
/// <param name="section">The section.</param>
/// <returns>A list of all keys.</returns>
public override List<string> ReadAllKeys(string section)
{
const int BUFFER_SIZE = 2500;
string temp = new('\0', BUFFER_SIZE);
int numBytes = NativeMethods.GetPrivateProfileString(section, null, "", temp, BUFFER_SIZE, _fileName);
List<string> keyList = new List<string>();
if (numBytes == 0)
{
return keyList;
}
temp = temp.TrimEnd('\0');
keyList.AddRange(temp.Split('\0'));
return keyList;
}
/// <summary>
/// Returns a list of all of the sections in the ini file.
/// </summary>
/// <returns>A list of all sections.</returns>
public override List<string> ReadAllSections()
{
List<string> sectionList = new();
// allocate a 10K buffer.
const int BUFFER_SIZE = 10240;
// allocate a 10K buffer. Should be enough to handle plenty of power systems
byte[] buffer = new byte[BUFFER_SIZE];
int numBytesReturned = NativeMethods.GetPrivateProfileSectionNames(buffer, BUFFER_SIZE, _fileName);
if (numBytesReturned == BUFFER_SIZE)
{
throw new Exception("IniFile::ReadAllSections() - returned the max buffer size. Probably have more items in config file than we can handle");
}
else if (numBytesReturned == 0)
{
return sectionList;
}
// convert the buffer to a string
string result = System.Text.Encoding.Unicode.GetString(buffer);
// trim the end of the string
result = result.TrimEnd('\0');
// split the string
string[] sectionListTemp = result.Split('\0');
// ass the sections to a list
for (int i = 0; i < sectionListTemp.Length; ++i)
{
sectionList.Add(sectionListTemp[i]);
}
return sectionList;
}
#endregion
}
}

View File

@@ -0,0 +1,385 @@
// ******************************************************************************//
// RAYTHEON PROPRIETARY: THIS DOCUMENT CONTAINS DATA OR INFORMATION
// PROPRIETARY TO RAYTHEON COMPANY AND IS RESTRICTED TO USE ONLY BY PERSONS
// AUTHORIZED BY RAYTHEON COMPANY IN WRITING TO USE IT. DISCLOSURE TO
// UNAUTHORIZED PERSONS WOULD LIKELY CAUSE SUBSTANTIAL COMPETITIVE HARM TO
// RAYTHEON COMPANY''S BUSINESS POSITION. NEITHER SAID DOCUMENT NOR ITS
// CONTENTS SHALL BE FURNISHED OR DISCLOSED TO OR COPIED OR USED BY PERSONS
// OUTSIDE RAYTHEON COMPANY WITHOUT THE EXPRESS WRITTEN APPROVAL OF RAYTHEON
// COMPANY.
//
// THIS PROPRIETARY NOTICE IS NOT APPLICABLE IF DELIVERED TO THE U.S. GOVERNMENT
//
// UNPUBLISHED WORK - COPYRIGHT RAYTHEON COMPANY.
//
// WARNING: THIS DOCUMENT CONTAINS TECHNICAL DATA AND / OR TECHNOLOGY WHOSE
// EXPORT OR DISCLOSURE TO NON-U.S. PERSONS, WHEREVER LOCATED, IS RESTRICTED
// BY THE INTERNATIONAL TRAFFIC IN ARMS REGULATIONS (ITAR) (22 C.F.R. SECTION
// 120-130) OR THE EXPORT ADMINISTRATION REGULATIONS (EAR) (15 C.F.R. SECTION
// 730-774). THIS DOCUMENT CANNOT BE EXPORTED (E.G., PROVIDED TO A SUPPLIER
// OUTSIDE OF THE UNITED STATES) OR DISCLOSED TO A NON-U.S. PERSON, WHEREVER
// LOCATED, UNTIL A FINAL JURISDICTION AND CLASSIFICATION DETERMINATION HAS
// BEEN COMPLETED AND APPROVED BY RAYTHEON, AND ANY REQUIRED U.S. GOVERNMENT
// APPROVALS HAVE BEEN OBTAINED. VIOLATIONS ARE SUBJECT TO SEVERE CRIMINAL
// PENALTIES.
//
// DOD 5220.22-M, INDUSTRIAL SECURITY MANUAL, CHAPTER 5, SECTION 1 THROUGH 9 :
// FOR CLASSIFIED DOCUMENTS FOLLOW THE PROCEDURES IN OR DOD 5200.1-R,
// INFORMATION SECURITY PROGRAM, CHAPTER 6. FOR UNCLASSIFIED, LIMITED DOCUMENTS
// DESTROY BY ANY METHOD THAT WILL PREVENT DISCLOSURE OF CONTENTS OR
// RECONSTRUCTION OF THE DOCUMENT.
// ****************************************************************************//
using System;
using System.IO;
using System.Linq;
using System.Xml.Linq;
namespace Raytheon.Common
{
/// <summary>
/// Implementation of the IConfiguration interface
/// </summary>
public class RaytheonConfiguration : IConfiguration
{
/// <summary>
/// returns configuration file path
/// </summary>
private string configFilePath
{
get
{
return Path.Combine(OutputPath, string.Concat(Name, ".xml"));
}
}
/// <summary>
/// configuration file name
/// </summary>
public string Name
{
get;
internal set;
}
/// <summary>
/// configuration file location
/// </summary>
public string OutputPath
{
get;
internal set;
}
/// <summary>
/// default constructor
/// </summary>
public RaytheonConfiguration()
{
OutputPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData), "Raytheon", "Configuration");
IsValidPath(OutputPath);
}
/// <summary>
/// constructor that takes configuration file name
/// </summary>
/// <param name="name"></param>
public RaytheonConfiguration(string name) : this()
{
Name = name;
}
/// <summary>
/// constructor that takes file name and location
/// </summary>
/// <param name="name"></param>
/// <param name="outputPath"></param>
public RaytheonConfiguration(string name, string outputPath) : this(name)
{
if (IsValidPath(outputPath))
{
OutputPath = outputPath;
}
}
private static void CreateConfigurationFile(FileInfo file)
{
XDocument xDocument = new XDocument();
xDocument.Add(new XElement("Configurations"));
xDocument.Root.Add(new XElement("IniConfiguration"));
xDocument.Root.Add(new XElement("XmlConfigurations"));
xDocument.Save(file.FullName);
}
private FileInfo CreateFileIfMissing()
{
FileInfo fileInfo = new FileInfo(configFilePath);
if (!fileInfo.Exists)
{
throw new Exception($"Can't find file: {configFilePath}");
}
return fileInfo;
}
private static XElement GetConfigSection(string section, XElement iniConfiguration, string configFilePath)
{
XElement xElement = (
from s in iniConfiguration.Descendants("section")
where (string)s.Attribute("name") == section
select s).FirstOrDefault();
if (xElement == null)
{
throw new Exception($"There is no <section> tag with 'name={section}' in {configFilePath}");
}
return xElement;
}
/// <summary>
/// reads single string value from XML configuration file by section name and a key
/// </summary>
/// <param name="section"></param>
/// <param name="key"></param>
/// <param name="defaultValue"></param>
/// <returns></returns>
public string GetConfigurationValue(string section, string key, string defaultValue)
{
FileInfo fileInfo = CreateFileIfMissing();
XDocument xDocument = XDocument.Load(fileInfo.FullName);
XElement xElement = xDocument.Root.Element("IniConfiguration");
XElement configSection = GetConfigSection(section, xElement, configFilePath);
XElement xElement1 = (
from k in configSection.Descendants("key")
where (string)k.Attribute("name") == key
select k).FirstOrDefault();
if (xElement1 == null)
{
XName xName = "key";
object[] xAttribute = new object[] { new XAttribute("name", key), new XAttribute("value", defaultValue) };
xElement1 = new XElement(xName, xAttribute);
configSection.Add(xElement1);
xDocument.Save(fileInfo.FullName);
}
XAttribute xAttribute1 = xElement1.Attribute("value");
if (xAttribute1 == null)
{
xAttribute1 = new XAttribute("value", defaultValue);
xElement1.Add(xAttribute1);
xDocument.Save(fileInfo.FullName);
}
if (xAttribute1 == null)
{
return null;
}
return xAttribute1.Value;
}
/// <summary>
/// reads single string value from XML configuration file by section name and a key
/// </summary>
/// <param name="section"></param>
/// <param name="key"></param>
/// <param name="defaultValue"></param>
/// <returns></returns>
public string GetConfigurationValue(string section, string key)
{
FileInfo fileInfo = CreateFileIfMissing();
XDocument xDocument = XDocument.Load(fileInfo.FullName);
XElement xElement = xDocument.Root.Element("IniConfiguration");
XElement configSection = GetConfigSection(section, xElement, configFilePath);
XElement xElement1 = (
from k in configSection.Descendants("key")
where (string)k.Attribute("name") == key
select k).FirstOrDefault();
if (xElement1 == null)
{
throw new Exception($"There is no <key> tag with 'name={key}' under section {section} in {configFilePath}");
}
XAttribute xAttribute1 = xElement1.Attribute("value");
if (xAttribute1 == null)
{
throw new Exception($"Attribute 'value' is missing for <key> tag with 'name={key}' under section {section} in {configFilePath}");
}
return xAttribute1.Value;
}
private static XElement GetConfigXml(string name, XElement xmlConfigurations)
{
XElement xElement = (
from s in xmlConfigurations.Descendants("XmlConfiguration")
where (string)s.Attribute("name") == name
select s).FirstOrDefault();
return xElement;
}
/// <summary>
/// reads XML configuration from a file
/// </summary>
/// <param name="name"></param>
/// <returns></returns>
public string GetXmlConfiguration(string name)
{
XDocument xDocument = XDocument.Load(CreateFileIfMissing().FullName);
XElement xElement = xDocument.Root.Element("XmlConfigurations");
XElement configXml = GetConfigXml(name, xElement);
if (configXml == null)
{
return string.Empty;
}
return configXml.ToString();
}
internal void Initialize()
{
Directory.CreateDirectory(OutputPath);
CreateFileIfMissing();
}
private static bool IsValidPath(string outputPath)
{
bool flag;
try
{
Directory.CreateDirectory(outputPath);
flag = true;
}
catch (PathTooLongException)
{
flag = false;
}
catch (UnauthorizedAccessException)
{
flag = false;
}
catch (ArgumentException)
{
flag = false;
}
catch (DirectoryNotFoundException)
{
flag = false;
}
catch (Exception)
{
throw;
}
return flag;
}
private static void SetConfigKey(string key, string value, XElement configSection)
{
XElement xElement = (
from k in configSection.Descendants("key")
where (string)k.Attribute("name") == key
select k).FirstOrDefault();
if (xElement != null)
{
xElement.SetAttributeValue("value", value);
return;
}
XName xName = "key";
object[] xAttribute = new object[] { new XAttribute("name", key), null };
xAttribute[1] = new XAttribute("value", value ?? string.Empty);
xElement = new XElement(xName, xAttribute);
configSection.Add(xElement);
}
/// <summary>
/// writes configuration value by section name and by key
/// </summary>
/// <param name="section"></param>
/// <param name="key"></param>
/// <param name="value"></param>
public void SetConfigurationValue(string section, string key, string value)
{
FileInfo fileInfo = CreateFileIfMissing();
XDocument xDocument = XDocument.Load(fileInfo.FullName);
XElement xElement = xDocument.Root.Element("IniConfiguration");
SetConfigKey(key, value, GetConfigSection(section, xElement, configFilePath));
xDocument.Save(fileInfo.FullName);
}
/// <summary>
/// saves XML string into XML file
/// </summary>
/// <param name="name"></param>
/// <param name="xml"></param>
public void SetXmlConfiguration(string name, string xml)
{
FileInfo fileInfo = CreateFileIfMissing();
XElement xElement = XElement.Parse(xml);
int elementCount = xElement.Elements().Count();
XDocument xDocument = XDocument.Load(fileInfo.FullName);
XElement xmlConfigurations = xDocument.Root.Element("XmlConfigurations");
XElement sectionXml = GetConfigXml(name, xmlConfigurations);
XName xName = "XmlConfiguration";
object[] xAttribute = new object[1 + elementCount];
xAttribute[0] = new XAttribute("name", name);
if (elementCount == 1)
{
xAttribute[1] = xElement.FirstNode;
}
else
{
int i = 1;
foreach (var item in xElement.Elements())
{
xAttribute[i++] = item;
}
}
if (sectionXml == null)
{
xmlConfigurations.Add(new XElement(xName, xAttribute));
}
else
{
sectionXml.ReplaceWith(new XElement(xName, xAttribute));
}
xDocument.Save(fileInfo.FullName);
}
/// <summary>
/// tries reading enumeration value by section and key name
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="section"></param>
/// <param name="key"></param>
/// <param name="value"></param>
/// <returns></returns>
/// <exception cref="ArgumentException"></exception>
public bool TryGetEnumValue<T>(string section, string key, out T value)
where T : struct
{
if (string.IsNullOrWhiteSpace(section))
{
throw new ArgumentException("'section' cannot be Null or Whitespace", "section");
}
if (string.IsNullOrWhiteSpace(key))
{
throw new ArgumentException("'key' cannot be Null or Whitespace", "key");
}
if (!typeof(T).IsEnum)
{
throw new ArgumentException("T must be an enumerated type");
}
bool flag = Enum.TryParse<T>(GetConfigurationValue(section, key, string.Concat("NOT_A_VALID_", key.ToUpper())), out value);
if (!flag)
{
int num = 0;
string[] names = Enum.GetNames(typeof(T));
for (int i = 0; i < names.Length; i++)
{
string str = names[i];
int num1 = num + 1;
num = num1;
int num2 = num1;
SetConfigurationValue(string.Concat("Valid_", key), num2.ToString(), str);
}
}
return flag;
}
}
}

View File

@@ -0,0 +1,161 @@
// ******************************************************************************//
// RAYTHEON PROPRIETARY: THIS DOCUMENT CONTAINS DATA OR INFORMATION
// PROPRIETARY TO RAYTHEON COMPANY AND IS RESTRICTED TO USE ONLY BY PERSONS
// AUTHORIZED BY RAYTHEON COMPANY IN WRITING TO USE IT. DISCLOSURE TO
// UNAUTHORIZED PERSONS WOULD LIKELY CAUSE SUBSTANTIAL COMPETITIVE HARM TO
// RAYTHEON COMPANY''S BUSINESS POSITION. NEITHER SAID DOCUMENT NOR ITS
// CONTENTS SHALL BE FURNISHED OR DISCLOSED TO OR COPIED OR USED BY PERSONS
// OUTSIDE RAYTHEON COMPANY WITHOUT THE EXPRESS WRITTEN APPROVAL OF RAYTHEON
// COMPANY.
//
// THIS PROPRIETARY NOTICE IS NOT APPLICABLE IF DELIVERED TO THE U.S. GOVERNMENT
//
// UNPUBLISHED WORK - COPYRIGHT RAYTHEON COMPANY.
//
// WARNING: THIS DOCUMENT CONTAINS TECHNICAL DATA AND / OR TECHNOLOGY WHOSE
// EXPORT OR DISCLOSURE TO NON-U.S. PERSONS, WHEREVER LOCATED, IS RESTRICTED
// BY THE INTERNATIONAL TRAFFIC IN ARMS REGULATIONS (ITAR) (22 C.F.R. SECTION
// 120-130) OR THE EXPORT ADMINISTRATION REGULATIONS (EAR) (15 C.F.R. SECTION
// 730-774). THIS DOCUMENT CANNOT BE EXPORTED (E.G., PROVIDED TO A SUPPLIER
// OUTSIDE OF THE UNITED STATES) OR DISCLOSED TO A NON-U.S. PERSON, WHEREVER
// LOCATED, UNTIL A FINAL JURISDICTION AND CLASSIFICATION DETERMINATION HAS
// BEEN COMPLETED AND APPROVED BY RAYTHEON, AND ANY REQUIRED U.S. GOVERNMENT
// APPROVALS HAVE BEEN OBTAINED. VIOLATIONS ARE SUBJECT TO SEVERE CRIMINAL
// PENALTIES.
//
// DOD 5220.22-M, INDUSTRIAL SECURITY MANUAL, CHAPTER 5, SECTION 1 THROUGH 9 :
// FOR CLASSIFIED DOCUMENTS FOLLOW THE PROCEDURES IN OR DOD 5200.1-R,
// INFORMATION SECURITY PROGRAM, CHAPTER 6. FOR UNCLASSIFIED, LIMITED DOCUMENTS
// DESTROY BY ANY METHOD THAT WILL PREVENT DISCLOSURE OF CONTENTS OR
// RECONSTRUCTION OF THE DOCUMENT.
// ****************************************************************************//
using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.Configuration;
using System.Diagnostics;
using System.IO;
namespace Raytheon.Common
{
/// <summary>
/// implementation of the Raytheon Configuration Manager
/// </summary>
[Export(typeof(IConfigurationManager))]
public class RaytheonConfigurationManager : IConfigurationManager
{
private object _configLock = new();
private Dictionary<string, RaytheonConfiguration> _configurations = new();
private static readonly string DefaultStoragePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData), "Raytheon", "InstrumentManagerService");
private string _storagePath;
/// <summary>
/// gets or sets configuration storage path
/// when setting the path and it does not exist will use the default value instead
/// </summary>
public string ConfigurationStoragePath
{
get
{
return _storagePath;
}
set
{
string item = value;
if(string.IsNullOrWhiteSpace(item))
{
item = ConfigurationManager.AppSettings["ConfigurationPath"];
}
if(!IsValidPath(item, true))
{
Trace.WriteLine(string.Format("The Application Setting [ConfigurationPath] '{0}' is invalid.", item));
_storagePath = DefaultStoragePath;
}
else
{
_storagePath = item;
}
}
}
/// <summary>
/// if path not provided will be using either app settings value or default
/// </summary>
public RaytheonConfigurationManager()
{
ConfigurationStoragePath = string.Empty;
}
/// <summary>
/// constructor that takes configuration file path
/// </summary>
/// <param name="defaultPath"></param>
public RaytheonConfigurationManager(string defaultPath) => ConfigurationStoragePath = defaultPath;
/// <summary>
/// returns RaytheonConfiguration instance
/// </summary>
/// <param name="configurationName"></param>
/// <returns></returns>
public IConfiguration GetConfiguration(string configurationName)
{
RaytheonConfiguration item = null;
lock(_configLock)
{
if(_configurations.ContainsKey(configurationName))
{
item = _configurations[configurationName];
}
else
{
item = new RaytheonConfiguration(configurationName, ConfigurationStoragePath);
item.Initialize();
_configurations.Add(configurationName, item);
}
}
return item;
}
/// <summary>
/// checks if the configuration storage path for config file is valid
/// </summary>
/// <param name="path"></param>
/// <param name="allowRelativePaths"></param>
/// <returns></returns>
private bool IsValidPath(string path, bool allowRelativePaths = false)
{
if(string.IsNullOrEmpty(path))
{
return false;
}
bool isValid;
try
{
string fullPath = Path.GetFullPath(path);
if(allowRelativePaths)
{
isValid = Path.IsPathRooted(path);
}
else
{
string root = Path.GetPathRoot(path);
isValid = string.IsNullOrEmpty(root.Trim(new char[] { '\\', '/' })) == false;
}
}
catch(Exception)
{
isValid = false;
}
return isValid;
}
}
}

View File

@@ -0,0 +1,156 @@
// ******************************************************************************//
// RAYTHEON PROPRIETARY: THIS DOCUMENT CONTAINS DATA OR INFORMATION
// PROPRIETARY TO RAYTHEON COMPANY AND IS RESTRICTED TO USE ONLY BY PERSONS
// AUTHORIZED BY RAYTHEON COMPANY IN WRITING TO USE IT. DISCLOSURE TO
// UNAUTHORIZED PERSONS WOULD LIKELY CAUSE SUBSTANTIAL COMPETITIVE HARM TO
// RAYTHEON COMPANY''S BUSINESS POSITION. NEITHER SAID DOCUMENT NOR ITS
// CONTENTS SHALL BE FURNISHED OR DISCLOSED TO OR COPIED OR USED BY PERSONS
// OUTSIDE RAYTHEON COMPANY WITHOUT THE EXPRESS WRITTEN APPROVAL OF RAYTHEON
// COMPANY.
//
// THIS PROPRIETARY NOTICE IS NOT APPLICABLE IF DELIVERED TO THE U.S. GOVERNMENT
//
// UNPUBLISHED WORK - COPYRIGHT RAYTHEON COMPANY.
//
// WARNING: THIS DOCUMENT CONTAINS TECHNICAL DATA AND / OR TECHNOLOGY WHOSE
// EXPORT OR DISCLOSURE TO NON-U.S. PERSONS, WHEREVER LOCATED, IS RESTRICTED
// BY THE INTERNATIONAL TRAFFIC IN ARMS REGULATIONS (ITAR) (22 C.F.R. SECTION
// 120-130) OR THE EXPORT ADMINISTRATION REGULATIONS (EAR) (15 C.F.R. SECTION
// 730-774). THIS DOCUMENT CANNOT BE EXPORTED (E.G., PROVIDED TO A SUPPLIER
// OUTSIDE OF THE UNITED STATES) OR DISCLOSED TO A NON-U.S. PERSON, WHEREVER
// LOCATED, UNTIL A FINAL JURISDICTION AND CLASSIFICATION DETERMINATION HAS
// BEEN COMPLETED AND APPROVED BY RAYTHEON, AND ANY REQUIRED U.S. GOVERNMENT
// APPROVALS HAVE BEEN OBTAINED. VIOLATIONS ARE SUBJECT TO SEVERE CRIMINAL
// PENALTIES.
//
// DOD 5220.22-M, INDUSTRIAL SECURITY MANUAL, CHAPTER 5, SECTION 1 THROUGH 9 :
// FOR CLASSIFIED DOCUMENTS FOLLOW THE PROCEDURES IN OR DOD 5200.1-R,
// INFORMATION SECURITY PROGRAM, CHAPTER 6. FOR UNCLASSIFIED, LIMITED DOCUMENTS
// DESTROY BY ANY METHOD THAT WILL PREVENT DISCLOSURE OF CONTENTS OR
// RECONSTRUCTION OF THE DOCUMENT.
// ****************************************************************************//
using System;
using System.Collections.Generic;
using System.IO;
namespace Raytheon.Common
{
/// <summary>
/// Read/Write to an XML file.
/// </summary>
public class XmlConfigurationFile : ConfigurationFileBase
{
#region PrivateMemberVariables
/// <summary>
/// Raytheon configuration
/// </summary>
private readonly IConfigurationManager _configurationManager;
private readonly IConfiguration _configuration;
#endregion
#region PublicFunctions
/// <summary>
/// The constructor. It will check to make sure the file exists and throw an exception it if does not
/// </summary>
/// <param name="fileName">The ini file name (path).</param>
public XmlConfigurationFile(string fileName)
: base(fileName)
{
if (ConfigurationFileType != ConfigurationFileType.XML)
{
throw new ArgumentException("Expecting XML file configuration type");
}
_configurationManager = new RaytheonConfigurationManager(_fileInfo.DirectoryName);
_configuration = _configurationManager.GetConfiguration(NameWithoutExtension(_fileInfo));
}
private static string NameWithoutExtension(FileInfo fileInfo)
{
return fileInfo.Name.Remove(fileInfo.Name.LastIndexOf("."));
}
/// <summary>
/// reads a value from configuration file
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="section"></param>
/// <param name="key"></param>
/// <param name="defaultValue"></param>
/// <returns></returns>
public override T ReadValue<T>(string section, string key, T defaultValue = default)
{
return _configuration.GetConfigurationValue<T>(section, key, defaultValue);
}
/// <summary>
/// reads a value from configuration file
/// </summary>
/// <param name="section"></param>
/// <param name="key"></param>
/// <returns></returns>
public override string ReadValue(string section, string key)
{
return _configuration.GetConfigurationValue(section, key);
}
/// <summary>
/// Write string value
/// </summary>
/// <param name="section"></param>
/// <param name="key"></param>
/// <param name="lineToWrite"></param>
public override void WriteValue<T>(string section, string key, T lineToWrite)
{
_configuration.SetConfigurationValue<T>(section, key, lineToWrite);
}
/// <summary>
/// reads a list of values from configuration file
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="section"></param>
/// <param name="key"></param>
/// <param name="defaultList"></param>
/// <returns></returns>
public override List<T> ReadList<T>(string section, string key, IList<T> defaultList = null)
{
return _configuration.GetConfigurationListValue<T>(section, key, defaultList);
}
/// <summary>
/// writes a list of values to configuration file
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="section"></param>
/// <param name="key"></param>
/// <param name="listToWrite"></param>
public override void WriteList<T>(string section, string key, IList<T> listToWrite)
{
_configuration.SetConfigurationListValue(section, key, listToWrite);
}
/// <summary>
/// Reads all keys from a section of an ini file.
/// </summary>
/// <param name="section">The section.</param>
/// <returns>A list of all keys.</returns>
public override List<string> ReadAllKeys(string section)
{
return ConfigurationHelper.GetAvailableConfigSectionKeys(_fileName, section);
}
/// <summary>
/// Returns a list of all of the sections in the ini file.
/// </summary>
/// <returns>A list of all sections.</returns>
public override List<string> ReadAllSections()
{
return ConfigurationHelper.GetAvailableConfigSections(_fileName);
}
#endregion
}
}

View File

@@ -0,0 +1,65 @@
// ******************************************************************************//
// RAYTHEON PROPRIETARY: THIS DOCUMENT CONTAINS DATA OR INFORMATION
// PROPRIETARY TO RAYTHEON COMPANY AND IS RESTRICTED TO USE ONLY BY PERSONS
// AUTHORIZED BY RAYTHEON COMPANY IN WRITING TO USE IT. DISCLOSURE TO
// UNAUTHORIZED PERSONS WOULD LIKELY CAUSE SUBSTANTIAL COMPETITIVE HARM TO
// RAYTHEON COMPANY''S BUSINESS POSITION. NEITHER SAID DOCUMENT NOR ITS
// CONTENTS SHALL BE FURNISHED OR DISCLOSED TO OR COPIED OR USED BY PERSONS
// OUTSIDE RAYTHEON COMPANY WITHOUT THE EXPRESS WRITTEN APPROVAL OF RAYTHEON
// COMPANY.
//
// THIS PROPRIETARY NOTICE IS NOT APPLICABLE IF DELIVERED TO THE U.S. GOVERNMENT
//
// UNPUBLISHED WORK - COPYRIGHT RAYTHEON COMPANY.
//
// WARNING: THIS DOCUMENT CONTAINS TECHNICAL DATA AND / OR TECHNOLOGY WHOSE
// EXPORT OR DISCLOSURE TO NON-U.S. PERSONS, WHEREVER LOCATED, IS RESTRICTED
// BY THE INTERNATIONAL TRAFFIC IN ARMS REGULATIONS (ITAR) (22 C.F.R. SECTION
// 120-130) OR THE EXPORT ADMINISTRATION REGULATIONS (EAR) (15 C.F.R. SECTION
// 730-774). THIS DOCUMENT CANNOT BE EXPORTED (E.G., PROVIDED TO A SUPPLIER
// OUTSIDE OF THE UNITED STATES) OR DISCLOSED TO A NON-U.S. PERSON, WHEREVER
// LOCATED, UNTIL A FINAL JURISDICTION AND CLASSIFICATION DETERMINATION HAS
// BEEN COMPLETED AND APPROVED BY RAYTHEON, AND ANY REQUIRED U.S. GOVERNMENT
// APPROVALS HAVE BEEN OBTAINED. VIOLATIONS ARE SUBJECT TO SEVERE CRIMINAL
// PENALTIES.
//
// DOD 5220.22-M, INDUSTRIAL SECURITY MANUAL, CHAPTER 5, SECTION 1 THROUGH 9 :
// FOR CLASSIFIED DOCUMENTS FOLLOW THE PROCEDURES IN OR DOD 5200.1-R,
// INFORMATION SECURITY PROGRAM, CHAPTER 6. FOR UNCLASSIFIED, LIMITED DOCUMENTS
// DESTROY BY ANY METHOD THAT WILL PREVENT DISCLOSURE OF CONTENTS OR
// RECONSTRUCTION OF THE DOCUMENT.
// ****************************************************************************//
using System;
using System.Runtime.Serialization;
namespace Raytheon.Common
{
[DataContract]
public class ConfigurationException : Exception
{
public ConfigurationException()
:base()
{
}
public ConfigurationException(string message)
:base(message)
{
}
public ConfigurationException(string message, Exception innerException)
:base(message, innerException)
{
}
public ConfigurationException(SerializationInfo info, StreamingContext context)
:base(info, context)
{
}
}
}

View File

@@ -0,0 +1,43 @@
// ******************************************************************************//
// RAYTHEON PROPRIETARY: THIS DOCUMENT CONTAINS DATA OR INFORMATION
// PROPRIETARY TO RAYTHEON COMPANY AND IS RESTRICTED TO USE ONLY BY PERSONS
// AUTHORIZED BY RAYTHEON COMPANY IN WRITING TO USE IT. DISCLOSURE TO
// UNAUTHORIZED PERSONS WOULD LIKELY CAUSE SUBSTANTIAL COMPETITIVE HARM TO
// RAYTHEON COMPANY''S BUSINESS POSITION. NEITHER SAID DOCUMENT NOR ITS
// CONTENTS SHALL BE FURNISHED OR DISCLOSED TO OR COPIED OR USED BY PERSONS
// OUTSIDE RAYTHEON COMPANY WITHOUT THE EXPRESS WRITTEN APPROVAL OF RAYTHEON
// COMPANY.
//
// THIS PROPRIETARY NOTICE IS NOT APPLICABLE IF DELIVERED TO THE U.S. GOVERNMENT
//
// UNPUBLISHED WORK - COPYRIGHT RAYTHEON COMPANY.
//
// WARNING: THIS DOCUMENT CONTAINS TECHNICAL DATA AND / OR TECHNOLOGY WHOSE
// EXPORT OR DISCLOSURE TO NON-U.S. PERSONS, WHEREVER LOCATED, IS RESTRICTED
// BY THE INTERNATIONAL TRAFFIC IN ARMS REGULATIONS (ITAR) (22 C.F.R. SECTION
// 120-130) OR THE EXPORT ADMINISTRATION REGULATIONS (EAR) (15 C.F.R. SECTION
// 730-774). THIS DOCUMENT CANNOT BE EXPORTED (E.G., PROVIDED TO A SUPPLIER
// OUTSIDE OF THE UNITED STATES) OR DISCLOSED TO A NON-U.S. PERSON, WHEREVER
// LOCATED, UNTIL A FINAL JURISDICTION AND CLASSIFICATION DETERMINATION HAS
// BEEN COMPLETED AND APPROVED BY RAYTHEON, AND ANY REQUIRED U.S. GOVERNMENT
// APPROVALS HAVE BEEN OBTAINED. VIOLATIONS ARE SUBJECT TO SEVERE CRIMINAL
// PENALTIES.
//
// DOD 5220.22-M, INDUSTRIAL SECURITY MANUAL, CHAPTER 5, SECTION 1 THROUGH 9 :
// FOR CLASSIFIED DOCUMENTS FOLLOW THE PROCEDURES IN OR DOD 5200.1-R,
// INFORMATION SECURITY PROGRAM, CHAPTER 6. FOR UNCLASSIFIED, LIMITED DOCUMENTS
// DESTROY BY ANY METHOD THAT WILL PREVENT DISCLOSURE OF CONTENTS OR
// RECONSTRUCTION OF THE DOCUMENT.
// ****************************************************************************//
namespace Raytheon.Common
{
/// <summary>
/// interface for flaging the moment when configurable object is done with configuration
/// restored from the previous version of Raytheon.Configuration package
/// </summary>
public interface IConfigurable
{
void OnConfigured();
}
}

View File

@@ -0,0 +1,92 @@
// ******************************************************************************//
// RAYTHEON PROPRIETARY: THIS DOCUMENT CONTAINS DATA OR INFORMATION
// PROPRIETARY TO RAYTHEON COMPANY AND IS RESTRICTED TO USE ONLY BY PERSONS
// AUTHORIZED BY RAYTHEON COMPANY IN WRITING TO USE IT. DISCLOSURE TO
// UNAUTHORIZED PERSONS WOULD LIKELY CAUSE SUBSTANTIAL COMPETITIVE HARM TO
// RAYTHEON COMPANY''S BUSINESS POSITION. NEITHER SAID DOCUMENT NOR ITS
// CONTENTS SHALL BE FURNISHED OR DISCLOSED TO OR COPIED OR USED BY PERSONS
// OUTSIDE RAYTHEON COMPANY WITHOUT THE EXPRESS WRITTEN APPROVAL OF RAYTHEON
// COMPANY.
//
// THIS PROPRIETARY NOTICE IS NOT APPLICABLE IF DELIVERED TO THE U.S. GOVERNMENT
//
// UNPUBLISHED WORK - COPYRIGHT RAYTHEON COMPANY.
//
// WARNING: THIS DOCUMENT CONTAINS TECHNICAL DATA AND / OR TECHNOLOGY WHOSE
// EXPORT OR DISCLOSURE TO NON-U.S. PERSONS, WHEREVER LOCATED, IS RESTRICTED
// BY THE INTERNATIONAL TRAFFIC IN ARMS REGULATIONS (ITAR) (22 C.F.R. SECTION
// 120-130) OR THE EXPORT ADMINISTRATION REGULATIONS (EAR) (15 C.F.R. SECTION
// 730-774). THIS DOCUMENT CANNOT BE EXPORTED (E.G., PROVIDED TO A SUPPLIER
// OUTSIDE OF THE UNITED STATES) OR DISCLOSED TO A NON-U.S. PERSON, WHEREVER
// LOCATED, UNTIL A FINAL JURISDICTION AND CLASSIFICATION DETERMINATION HAS
// BEEN COMPLETED AND APPROVED BY RAYTHEON, AND ANY REQUIRED U.S. GOVERNMENT
// APPROVALS HAVE BEEN OBTAINED. VIOLATIONS ARE SUBJECT TO SEVERE CRIMINAL
// PENALTIES.
//
// DOD 5220.22-M, INDUSTRIAL SECURITY MANUAL, CHAPTER 5, SECTION 1 THROUGH 9 :
// FOR CLASSIFIED DOCUMENTS FOLLOW THE PROCEDURES IN OR DOD 5200.1-R,
// INFORMATION SECURITY PROGRAM, CHAPTER 6. FOR UNCLASSIFIED, LIMITED DOCUMENTS
// DESTROY BY ANY METHOD THAT WILL PREVENT DISCLOSURE OF CONTENTS OR
// RECONSTRUCTION OF THE DOCUMENT.
// ****************************************************************************//
namespace Raytheon.Common
{
/// <summary>
/// Configuration interface
/// restored from the previous version of Raytheon.Configuration package
/// </summary>
public interface IConfiguration
{
/// <summary>
/// Sets the configuration value.
/// </summary>
/// <param name="section">The section.</param>
/// <param name="key">The key.</param>
/// <param name="value">The value.</param>
void SetConfigurationValue(string section, string key, string value);
/// <summary>
/// Gets the configuration value.
/// </summary>
/// <param name="section">The section.</param>
/// <param name="key">The key.</param>
/// <param name="defaultValue">The default value.</param>
/// <returns></returns>
string GetConfigurationValue(string section, string key, string defaultValue);
/// <summary>
/// Gets the configuration value.
/// </summary>
/// <param name="section">The section.</param>
/// <param name="key">The key.</param>
/// <returns></returns>
string GetConfigurationValue(string section, string key);
/// <summary>
/// Sets the XML configuration.
/// </summary>
/// <param name="name">The name.</param>
/// <param name="xml">The XML.</param>
void SetXmlConfiguration(string name, string xml);
/// <summary>
/// Gets the XML configuration.
/// </summary>
/// <param name="name">The name.</param>
/// <returns></returns>
string GetXmlConfiguration(string name);
/// <summary>
/// Attempts to get the enumerated configuration value.
/// If it does not exist or cannot be parsed to a valid value,
/// it will create a new section called Valid_{key} and list the valid enumeration values.
/// </summary>
/// <param name="section">The section.</param>
/// <param name="key">The key.</param>
/// <param name="defaultValue">The default value.</param>
/// <returns></returns>
bool TryGetEnumValue<T>(string section, string key, out T value) where T : struct;
}
}

View File

@@ -0,0 +1,137 @@
// ******************************************************************************//
// RAYTHEON PROPRIETARY: THIS DOCUMENT CONTAINS DATA OR INFORMATION
// PROPRIETARY TO RAYTHEON COMPANY AND IS RESTRICTED TO USE ONLY BY PERSONS
// AUTHORIZED BY RAYTHEON COMPANY IN WRITING TO USE IT. DISCLOSURE TO
// UNAUTHORIZED PERSONS WOULD LIKELY CAUSE SUBSTANTIAL COMPETITIVE HARM TO
// RAYTHEON COMPANY''S BUSINESS POSITION. NEITHER SAID DOCUMENT NOR ITS
// CONTENTS SHALL BE FURNISHED OR DISCLOSED TO OR COPIED OR USED BY PERSONS
// OUTSIDE RAYTHEON COMPANY WITHOUT THE EXPRESS WRITTEN APPROVAL OF RAYTHEON
// COMPANY.
//
// THIS PROPRIETARY NOTICE IS NOT APPLICABLE IF DELIVERED TO THE U.S. GOVERNMENT
//
// UNPUBLISHED WORK - COPYRIGHT RAYTHEON COMPANY.
//
// WARNING: THIS DOCUMENT CONTAINS TECHNICAL DATA AND / OR TECHNOLOGY WHOSE
// EXPORT OR DISCLOSURE TO NON-U.S. PERSONS, WHEREVER LOCATED, IS RESTRICTED
// BY THE INTERNATIONAL TRAFFIC IN ARMS REGULATIONS (ITAR) (22 C.F.R. SECTION
// 120-130) OR THE EXPORT ADMINISTRATION REGULATIONS (EAR) (15 C.F.R. SECTION
// 730-774). THIS DOCUMENT CANNOT BE EXPORTED (E.G., PROVIDED TO A SUPPLIER
// OUTSIDE OF THE UNITED STATES) OR DISCLOSED TO A NON-U.S. PERSON, WHEREVER
// LOCATED, UNTIL A FINAL JURISDICTION AND CLASSIFICATION DETERMINATION HAS
// BEEN COMPLETED AND APPROVED BY RAYTHEON, AND ANY REQUIRED U.S. GOVERNMENT
// APPROVALS HAVE BEEN OBTAINED. VIOLATIONS ARE SUBJECT TO SEVERE CRIMINAL
// PENALTIES.
//
// DOD 5220.22-M, INDUSTRIAL SECURITY MANUAL, CHAPTER 5, SECTION 1 THROUGH 9 :
// FOR CLASSIFIED DOCUMENTS FOLLOW THE PROCEDURES IN OR DOD 5200.1-R,
// INFORMATION SECURITY PROGRAM, CHAPTER 6. FOR UNCLASSIFIED, LIMITED DOCUMENTS
// DESTROY BY ANY METHOD THAT WILL PREVENT DISCLOSURE OF CONTENTS OR
// RECONSTRUCTION OF THE DOCUMENT.
// ****************************************************************************//
using System.Collections.Generic;
namespace Raytheon.Common
{
/// <summary>
/// supported file types
/// </summary>
public enum ConfigurationFileType
{
INI,
XML,
TOML,
JSON,
YAML,
OTHER
}
/// <summary>
/// updated version of IConfiguration interface
/// allows reading and writing generic types as well as lists
/// </summary>
public interface IConfigurationFile
{
/// <summary>
/// reads a single generic type value from the file section
/// if value or section does not exist, will create one and will add the default value
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="section"></param>
/// <param name="key"></param>
/// <param name="defValue"></param>
/// <returns></returns>
T ReadValue<T>(string section, string key, T defValue = default);
/// <summary>
/// reads a single generic type value from the file section
/// if value doesn't exist, throw exception
/// </summary>
/// <param name="section"></param>
/// <param name="key"></param>
/// <returns></returns>
string ReadValue(string section, string key);
/// <summary>
/// reads a list of generic type values from the file section
/// if list or section does not exist, will create one and will populate with the default list
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="section"></param>
/// <param name="key"></param>
/// <param name="defList"></param>
/// <returns></returns>
List<T> ReadList<T>(string section, string key, IList<T> defList = null);
/// <summary>
/// reads all available keys from the given section of configuration file
/// </summary>
/// <param name="section"></param>
/// <returns></returns>
List<string> ReadAllKeys(string section);
/// <summary>
/// reads all available sections from configuration file
/// </summary>
/// <returns></returns>
List<string> ReadAllSections();
/// <summary>
/// writes a single value of a generic type
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="section"></param>
/// <param name="key"></param>
/// <param name="lineToWrite"></param>
void WriteValue<T>(string section, string key, T lineToWrite);
/// <summary>
/// writes a list of generic values
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="section"></param>
/// <param name="key"></param>
/// <param name="listToWrite"></param>
void WriteList<T>(string section, string key, IList<T> listToWrite);
/// <summary>
/// checks if the value exists in the given section and given key
/// </summary>
/// <param name="section"></param>
/// <param name="key"></param>
/// <returns></returns>
bool ValueExists(string section, string key);
/// <summary>
/// configuration file name
/// </summary>
string FileName { get; }
/// <summary>
/// configuration file type
/// </summary>
ConfigurationFileType ConfigurationFileType { get; }
}
}

View File

@@ -0,0 +1,52 @@
// ******************************************************************************//
// RAYTHEON PROPRIETARY: THIS DOCUMENT CONTAINS DATA OR INFORMATION
// PROPRIETARY TO RAYTHEON COMPANY AND IS RESTRICTED TO USE ONLY BY PERSONS
// AUTHORIZED BY RAYTHEON COMPANY IN WRITING TO USE IT. DISCLOSURE TO
// UNAUTHORIZED PERSONS WOULD LIKELY CAUSE SUBSTANTIAL COMPETITIVE HARM TO
// RAYTHEON COMPANY''S BUSINESS POSITION. NEITHER SAID DOCUMENT NOR ITS
// CONTENTS SHALL BE FURNISHED OR DISCLOSED TO OR COPIED OR USED BY PERSONS
// OUTSIDE RAYTHEON COMPANY WITHOUT THE EXPRESS WRITTEN APPROVAL OF RAYTHEON
// COMPANY.
//
// THIS PROPRIETARY NOTICE IS NOT APPLICABLE IF DELIVERED TO THE U.S. GOVERNMENT
//
// UNPUBLISHED WORK - COPYRIGHT RAYTHEON COMPANY.
//
// WARNING: THIS DOCUMENT CONTAINS TECHNICAL DATA AND / OR TECHNOLOGY WHOSE
// EXPORT OR DISCLOSURE TO NON-U.S. PERSONS, WHEREVER LOCATED, IS RESTRICTED
// BY THE INTERNATIONAL TRAFFIC IN ARMS REGULATIONS (ITAR) (22 C.F.R. SECTION
// 120-130) OR THE EXPORT ADMINISTRATION REGULATIONS (EAR) (15 C.F.R. SECTION
// 730-774). THIS DOCUMENT CANNOT BE EXPORTED (E.G., PROVIDED TO A SUPPLIER
// OUTSIDE OF THE UNITED STATES) OR DISCLOSED TO A NON-U.S. PERSON, WHEREVER
// LOCATED, UNTIL A FINAL JURISDICTION AND CLASSIFICATION DETERMINATION HAS
// BEEN COMPLETED AND APPROVED BY RAYTHEON, AND ANY REQUIRED U.S. GOVERNMENT
// APPROVALS HAVE BEEN OBTAINED. VIOLATIONS ARE SUBJECT TO SEVERE CRIMINAL
// PENALTIES.
//
// DOD 5220.22-M, INDUSTRIAL SECURITY MANUAL, CHAPTER 5, SECTION 1 THROUGH 9 :
// FOR CLASSIFIED DOCUMENTS FOLLOW THE PROCEDURES IN OR DOD 5200.1-R,
// INFORMATION SECURITY PROGRAM, CHAPTER 6. FOR UNCLASSIFIED, LIMITED DOCUMENTS
// DESTROY BY ANY METHOD THAT WILL PREVENT DISCLOSURE OF CONTENTS OR
// RECONSTRUCTION OF THE DOCUMENT.
// ****************************************************************************//
namespace Raytheon.Common
{
/// <summary>
/// Configuration Manager interface
/// </summary>
public interface IConfigurationManager
{
/// <summary>
/// Gets the configuration by name.
/// </summary>
/// <param name="configurationName">Name of the configuration.</param>
/// <returns></returns>
IConfiguration GetConfiguration(string configurationName);
/// <summary>
/// Gets or sets the configuration storage path or the location of the configuration files
/// </summary>
string ConfigurationStoragePath { get; set; }
}
}

View File

@@ -0,0 +1,54 @@
// UNCLASSIFIED
/*-------------------------------------------------------------------------
RAYTHEON PROPRIETARY: THIS DOCUMENT CONTAINS DATA OR INFORMATION
PROPRIETARY TO RAYTHEON COMPANY AND IS RESTRICTED TO USE ONLY BY PERSONS
AUTHORIZED BY RAYTHEON COMPANY IN WRITING TO USE IT. DISCLOSURE TO
UNAUTHORIZED PERSONS WOULD LIKELY CAUSE SUBSTANTIAL COMPETITIVE HARM TO
RAYTHEON COMPANY'S BUSINESS POSITION. NEITHER SAID DOCUMENT NOR ITS
CONTENTS SHALL BE FURNISHED OR DISCLOSED TO OR COPIED OR USED BY PERSONS
OUTSIDE RAYTHEON COMPANY WITHOUT THE EXPRESS WRITTEN APPROVAL OF RAYTHEON
COMPANY.
THIS PROPRIETARY NOTICE IS NOT APPLICABLE IF DELIVERED TO THE U.S.
GOVERNMENT.
UNPUBLISHED WORK - COPYRIGHT RAYTHEON COMPANY.
-------------------------------------------------------------------------*/
using System;
using System.Text;
namespace FpgaMeasurementInstrumentsLib
{
/// <summary>
/// A collection of utilities.
/// </summary>
public static class HssUtilSs
{
#region PublicFuctions
/// <summary>
///
/// </summary>
/// <param name="chassisHandle"></param>
/// <param name="errorCode"></param>
/// <param name="moduleName"></param>
/// <returns></returns>
public static string BuildErrorString(uint chassisHandle, int errorCode, string moduleName)
{
StringBuilder errorStrTemp = new StringBuilder(512);
int ret = HssubNativeMethods.terHsi_error_message(chassisHandle, errorCode, errorStrTemp);
if (ret != 0)
{
throw new Exception("HssUtilSs::BuildErrorString() - terHsi_error_message returned an error(" + ret + ")");
}
string errorMsg = errorStrTemp.ToString();
return errorMsg += "(" + moduleName + ")";
}
#endregion
}
}

View File

@@ -0,0 +1,119 @@
// UNCLASSIFIED
/*-------------------------------------------------------------------------
RAYTHEON PROPRIETARY: THIS DOCUMENT CONTAINS DATA OR INFORMATION
PROPRIETARY TO RAYTHEON COMPANY AND IS RESTRICTED TO USE ONLY BY PERSONS
AUTHORIZED BY RAYTHEON COMPANY IN WRITING TO USE IT. DISCLOSURE TO
UNAUTHORIZED PERSONS WOULD LIKELY CAUSE SUBSTANTIAL COMPETITIVE HARM TO
RAYTHEON COMPANY'S BUSINESS POSITION. NEITHER SAID DOCUMENT NOR ITS
CONTENTS SHALL BE FURNISHED OR DISCLOSED TO OR COPIED OR USED BY PERSONS
OUTSIDE RAYTHEON COMPANY WITHOUT THE EXPRESS WRITTEN APPROVAL OF RAYTHEON
COMPANY.
THIS PROPRIETARY NOTICE IS NOT APPLICABLE IF DELIVERED TO THE U.S.
GOVERNMENT.
UNPUBLISHED WORK - COPYRIGHT RAYTHEON COMPANY.
-------------------------------------------------------------------------*/
using System;
using System.Runtime.InteropServices;
using System.Text;
namespace FpgaMeasurementInstrumentsLib
{
/// <summary>
/// A collection of utilities.
/// </summary>
public static class HssUtilTs
{
public struct LocalBusParams
{
public int cardHandle;
public int address;
public int data;
}
#region PublicFuctions
/// <summary>
///
/// </summary>
/// <param name="chassisHandle"></param>
/// <param name="errorCode"></param>
/// <param name="moduleName"></param>
/// <returns></returns>
public static string BuildErrorString(uint chassisHandle, int errorCode, string moduleName)
{
StringBuilder errorStrTemp = new StringBuilder(512);
int ret = HssubNativeMethods.terHss_error_message(chassisHandle, errorCode, errorStrTemp);
if (ret != 0)
{
throw new Exception("HssUtilTs::BuildErrorString() - terHss_error_message returned an error(" + ret + ")");
}
string errorMsg = errorStrTemp.ToString();
return errorMsg += "(" + moduleName + ")";
}
/// <summary>
///
/// </summary>
/// <param name="data"></param>
/// <returns></returns>
public static LocalBusParams ByteArrayToLocalBusParms(byte[] data)
{
GCHandle rxPinnedArray = GCHandle.Alloc(data, GCHandleType.Pinned);
IntPtr pBytePtr = rxPinnedArray.AddrOfPinnedObject();
LocalBusParams lbParams = (LocalBusParams)(Marshal.PtrToStructure(pBytePtr, typeof(LocalBusParams)));
rxPinnedArray.Free();
return lbParams;
}
/// <summary>
///
/// </summary>
/// <param name="lbParams"></param>
/// <returns></returns>
public static byte[] LocalBusParmsToByteArray(LocalBusParams lbParams)
{
// get the size of the structure
int structureSize = Marshal.SizeOf(lbParams);
// allocate a byte array
byte[] dataToSend = new byte[structureSize];
// convert structure to byte array
IntPtr pBytePtr = Marshal.AllocHGlobal(structureSize);
Marshal.StructureToPtr(lbParams, pBytePtr, true);
Marshal.Copy(pBytePtr, dataToSend, 0, structureSize);
Marshal.FreeHGlobal(pBytePtr);
return dataToSend;
}
/// <summary>
///
/// </summary>
/// <param name="chassisHandle"></param>
/// <param name="hssubSubSystemAppSync"></param>
/// <param name="name"></param>
public static void WaitForSync(uint chassisHandle, int hssubSubSystemAppSync, string name)
{
//0 is VI_FALSE, 1 is VI_TRUE
int hssubSyncData = 0;
int ret = HssubNativeMethods.terHss_Application_WaitForSyncObject(chassisHandle, hssubSubSystemAppSync, HssubNativeMethods.TERHSS_TIMEOUT_10SEC, 1, ref hssubSyncData);
if (ret != 0)
{
string errorStr = HssUtilTs.BuildErrorString(chassisHandle, ret, name);
throw new Exception("HssUtilTs::WaitForSync() - terHss_Application_WaitForSyncObject() returned an error(" + ret + ")" + ": " + errorStr);
}
}
#endregion
}
}

View File

@@ -0,0 +1,126 @@
// UNCLASSIFIED
/*-------------------------------------------------------------------------
RAYTHEON PROPRIETARY: THIS DOCUMENT CONTAINS DATA OR INFORMATION
PROPRIETARY TO RAYTHEON COMPANY AND IS RESTRICTED TO USE ONLY BY PERSONS
AUTHORIZED BY RAYTHEON COMPANY IN WRITING TO USE IT. DISCLOSURE TO
UNAUTHORIZED PERSONS WOULD LIKELY CAUSE SUBSTANTIAL COMPETITIVE HARM TO
RAYTHEON COMPANY'S BUSINESS POSITION. NEITHER SAID DOCUMENT NOR ITS
CONTENTS SHALL BE FURNISHED OR DISCLOSED TO OR COPIED OR USED BY PERSONS
OUTSIDE RAYTHEON COMPANY WITHOUT THE EXPRESS WRITTEN APPROVAL OF RAYTHEON
COMPANY.
THIS PROPRIETARY NOTICE IS NOT APPLICABLE IF DELIVERED TO THE U.S.
GOVERNMENT.
UNPUBLISHED WORK - COPYRIGHT RAYTHEON COMPANY.
-------------------------------------------------------------------------*/
using System.Runtime.InteropServices;
using System.Text;
namespace FpgaMeasurementInstrumentsLib
{
/// <summary>
///
/// </summary>
public unsafe static class HssubNativeMethods
{
public const int TERHSI_FPGA_TEST_DEFINED = 1;
// timeouts
public const int TERHSS_TIMEOUT_INDEFINITE = 0;
public const int TERHSS_TIMEOUT_60SEC = 60;
public const int TERHSS_TIMEOUT_10SEC = 10;
//
public const int TERHSS_OPTION_ALLOW_OVERWRITE = 1;
public const int TERHSS_OPTION_NONE = 0;
// callback codes
public const int MESSAGE_CONTEXT_INIT_INSTRUMENT = 0;
public const int MESSAGE_CONTEXT_LOAD_INSTRUMENT = 1;
public const int MESSAGE_CONTEXT_LB_WRITE32 = 2;
public const int MESSAGE_CONTEXT_LB_READ32 = 3;
public const int MESSAGE_CONTEXT_PAM_BLOCK_CREATE = 4;
public const int MESSAGE_CONTEXT_PAM_BLOCK_READ = 5;
public const int MESSAGE_CONTEXT_NBLOCK_WRITE = 6;
public const int MESSAGE_CONTEXT_NBLOCK_READ = 7;
public const int MESSAGE_CONTEXT_RUN_EXE = 8;
public const int MESSAGE_CONTEXT_RUN_JTAG = 9;
public const int MESSAGE_CONTEXT_DMA_CREATE_PAM_BLOCK = 10;
public const int MESSAGE_CONTEXT_DMA_READ_PAM_BLOCK = 11;
public const int MESSAGE_CONTEXT_DMA_WRITE_PAM_BLOCK = 12;
public const int MESSAGE_CONTEXT_DMA_MEMORY_MOVE = 13;
public const int MESSAGE_CONTEXT_DMA_PAM_CLEAR = 14;
public const int MESSAGE_CONTEXT_UCLK_SET = 20;
// HSS imports (running on the remote test station)
public delegate void MessageCallbackDelagate(uint chassisHandle, int applicationHandle, int messageContext, uint messageSize, byte* message);
[DllImport("C:\\Program Files (x86)\\IVI Foundation\\IVI\\Bin\\terHss.dll", CallingConvention = CallingConvention.StdCall)]
public static extern int terHss_error_message(uint chassisHandle, int errorCode, StringBuilder errorMessage);
[DllImport("C:\\Program Files (x86)\\IVI Foundation\\IVI\\Bin\\terHss.dll", CallingConvention = CallingConvention.StdCall)]
public static extern int terHss_init(string resourceName, ushort idQuery, ushort reset, ref uint pdwVi);
[DllImport("C:\\Program Files (x86)\\IVI Foundation\\IVI\\Bin\\terHss.dll", CallingConvention = CallingConvention.StdCall)]
public static extern int terHss_Application_CreateSyncObject(uint chassisHandle, string syncName, ref int syncObjectHandle);
[DllImport("C:\\Program Files (x86)\\IVI Foundation\\IVI\\Bin\\terHss.dll", CallingConvention = CallingConvention.StdCall)]
public static extern int terHss_Application_RegisterMessageCallback(uint chassisHandle, MessageCallbackDelagate callback);
[DllImport("C:\\Program Files (x86)\\IVI Foundation\\IVI\\Bin\\terHss.dll", CallingConvention = CallingConvention.StdCall)]
public static extern int terHss_Subsystem_SendFile(uint chassisHandle, string sourceFile, string destinationFile, int options);
[DllImport("C:\\Program Files (x86)\\IVI Foundation\\IVI\\Bin\\terHss.dll", CallingConvention = CallingConvention.StdCall)]
public static extern int terHss_Application_Load(uint chassisHandle, string applicationName, string remotePath, ref int applicationHandle);
[DllImport("C:\\Program Files (x86)\\IVI Foundation\\IVI\\Bin\\terHss.dll", CallingConvention = CallingConvention.StdCall)]
public static extern int terHss_Application_Start(uint chassisHandle, int applicationHandle, string cmdLineArgs, double timeout);
[DllImport("C:\\Program Files (x86)\\IVI Foundation\\IVI\\Bin\\terHss.dll", CallingConvention = CallingConvention.StdCall)]
public static extern int terHss_Application_WaitForSyncObject(uint chassisHandle, int syncHandle, double timeout, ushort autoReset, ref int contextValue);
[DllImport("C:\\Program Files (x86)\\IVI Foundation\\IVI\\Bin\\terHss.dll", CallingConvention = CallingConvention.StdCall)]
public static extern int terHss_Application_SendMessage(uint chassisHandle, int applicationHandle, int messageContext, int messageArraySize, byte[] message, double timeout);
[DllImport("C:\\Program Files (x86)\\IVI Foundation\\IVI\\Bin\\terHss.dll", CallingConvention = CallingConvention.StdCall)]
public static extern int terHss_Subsystem_DeleteFile(uint chassisHandle, string file, int options);
[DllImport("C:\\Program Files (x86)\\IVI Foundation\\IVI\\Bin\\terHss.dll", CallingConvention = CallingConvention.StdCall)]
public static extern int terHss_close(uint chassisHandle);
[DllImport("C:\\Program Files (x86)\\IVI Foundation\\IVI\\Bin\\terHss.dll", CallingConvention = CallingConvention.StdCall)]
public static extern int terHss_self_test(uint chassisHandle, ref short result, StringBuilder message);
// HSI imports (running on the local sub system)
[DllImport("C:\\Program Files (x86)\\IVI Foundation\\IVI\\Bin\\terHsi_32.dll", CallingConvention = CallingConvention.StdCall)]
public static extern int terHsi_error_message(uint chassisHandle, int errorCode, StringBuilder errorMessage);
[DllImport("C:\\Program Files (x86)\\IVI Foundation\\IVI\\Bin\\terHsi_32.dll", CallingConvention = CallingConvention.StdCall)]
public static extern int terHsi_init(string resourceName, ushort idQuery, ushort reset, ref uint pdwVi);
[DllImport("C:\\Program Files (x86)\\IVI Foundation\\IVI\\Bin\\terHsi_32.dll", CallingConvention = CallingConvention.StdCall)]
public static extern int terHsi_Firmware_Load(uint chassisHandle, int fpga, string fwFileName, ref ushort customerId, ref ushort applicationID, ref uint revisionID);
[DllImport("C:\\Program Files (x86)\\IVI Foundation\\IVI\\Bin\\terHsi_32.dll", CallingConvention = CallingConvention.StdCall)]
public static extern int terHsi_LB_Read32(uint chassisHandle, uint offset, ref uint data);
[DllImport("C:\\Program Files (x86)\\IVI Foundation\\IVI\\Bin\\terHsi_32.dll", CallingConvention = CallingConvention.StdCall)]
public static extern int terHsi_LB_ReadBlock32(uint chassisHandle, uint offset, uint numberWordsToRead, uint* data);
[DllImport("C:\\Program Files (x86)\\IVI Foundation\\IVI\\Bin\\terHsi_32.dll", CallingConvention = CallingConvention.StdCall)]
public static extern int terHsi_LB_Write32(uint chassisHandle, uint offset, uint data);
[DllImport("C:\\Program Files (x86)\\IVI Foundation\\IVI\\Bin\\terHsi_32.dll", CallingConvention = CallingConvention.StdCall)]
public static extern int terHsi_LB_WriteBlock32(uint chassisHandle, uint offset, uint numberWordsToWrite, uint[] data);
//public static extern int terHsi_LB_WriteBlock32(uint chassisHandle, uint offset, uint numberWordsToWrite, uint* data);
[DllImport("C:\\Program Files (x86)\\IVI Foundation\\IVI\\Bin\\terHsi_32.dll", CallingConvention = CallingConvention.StdCall)]
public static extern int terHsi_close(uint chassisHandle);
[DllImport("C:\\Program Files (x86)\\IVI Foundation\\IVI\\Bin\\terHsi_32.dll", CallingConvention = CallingConvention.StdCall)]
public static extern int terHsi_reset(uint chassisHandle);
}
}

View File

@@ -0,0 +1,123 @@
// **********************************************************************************************************
// IDisplay.cs
// 2/17/2023
// NGI - Next Generation Interceptor
//
// Contract No. HQ0856-21-C-0003/1022000209
//
// THIS DOCUMENT DOES NOT CONTAIN TECHNOLOGY OR TECHNICAL DATA CONTROLLED UNDER EITHER THE U.S.
// INTERNATIONAL TRAFFIC IN ARMS REGULATIONS OR THE U.S. EXPORT ADMINISTRATION REGULATIONS.
//
// RAYTHEON PROPRIETARY: THIS DOCUMENT CONTAINS DATA OR INFORMATION PROPRIETARY TO RAYTHEON
// COMPANY AND IS RESTRICTED TO USE ONLY BY PERSONS AUTHORIZED BY RAYTHEON COMPANY IN WRITING TO USE IT.
// DISCLOSURE TO UNAUTHORIZED PERSONS WOULD LIKELY CAUSE SUBSTANTIAL COMPETITIVE HARM TO RAYTHEON
// COMPANY'S BUSINESS POSITION. NEITHER SAID DOCUMENT NOR ITS CONTENTS SHALL BE FURNISHED OR DISCLOSED
// TO OR COPIED OR USED BY PERSONS OUTSIDE RAYTHEON COMPANY WITHOUT THE EXPRESS WRITTEN APPROVAL OF
// RAYTHEON COMPANY.
//
// UNPUBLISHED WORK - COPYRIGHT RAYTHEON COMPANY.
//
// DESTRUCTION NOTICE: FOR CLASSIFIED DOCUMENTS FOLLOW THE PROCEDURES IN DOD 5220.22-M,
// NATIONAL INDUSTRIAL SECURITY PROGRAM OPERATING MANUAL, FEBRUARY 2006,
// INCORPORATING CHANGE 1, MARCH 28, 2013, CHAPTER 5, SECTION 7, OR DODM 5200.01-VOLUME 3,
// DOD INFORMATION SECURITY PROGRAM: PROTECTION OF CLASSIFIED INFORMATION, ENCLOSURE 3,
// SECTION 17. FOR CONTROLLED UNCLASSIFIED INFORMATION FOLLOW THE PROCEDURES IN DODM 5200.01-VOLUME 4,
// INFORMATION SECURITY PROGRAM: CONTROLLED UNCLASSIFIED INFORMATION.
//
// CONTROLLED BY: MISSILE DEFENSE AGENCY
// CONTROLLED BY: GROUND-BASED MIDCOURSE DEFENSE PROGRAM OFFICE
// CUI CATEGORY: CTI
// DISTRIBUTION/DISSEMINATION CONTROL: F
// POC: Alex Kravchenko (1118268)
// **********************************************************************************************************
using System.Collections.Generic;
namespace Raytheon.Common
{
/// <summary>
/// Enum for tagging the logged data.
/// </summary>
public enum LogLevel
{
/// <summary>
/// (Ordinal = 0) : Most verbose level. Used for development and seldom enabled in production.
/// </summary>
TRACE,
/// <summary>
/// (Ordinal = 1) : Debugging the application behavior from internal events of interest.
/// </summary>
DEBUG,
/// <summary>
/// An informational log statement.
/// (Ordinal = 2) : Information that highlights progress or application lifetime events.
/// </summary>
INFO,
/// <summary>
/// (Ordinal = 3) : Warnings about validation issues or temporary failures that can be recovered.
/// </summary>
WARN,
/// <summary>
/// (Ordinal = 4) : Errors where functionality has failed or <see cref="System.Exception"/> have been caught.
/// an error log statement.
/// </summary>
ERROR,
/// <summary>
/// (Ordinal = 5) : Most critical level. Application is about to abort.
/// </summary>
FATAL,
/// <summary>
/// Off log level (Ordinal = 6)
/// </summary>
OFF
}
public interface IDisplay
{
/// <summary>
/// user interface capability with error logger
/// </summary>
/// <param name="message"></param>
/// <param name="logLevel"></param>
void ShowMessage(string message, LogLevel logLevel = LogLevel.INFO);
}
public interface IChillerDisplay
{
void ChillerMonitorUiUpdate(ActiveHealthMonitorData data, int errorCode);
}
public interface IDioDisplay
{
void DioControlUiUpdate(List<string> inputNames, List<string> outputNames);
}
public interface IFpgaDisplay
{
void FpgaControlUiUpdate(List<string> fpgaNames);
}
public interface IPowerControlDisplay
{
void PowerControlUiUpdate(List<string> powerFormNames);
}
public interface IPowerMonitorDisplay
{
void PowerMonitorUiUpdate(List<PowerMonitorCallbackData> callBackDataList, int errorCode);
}
public interface IHealthMonitorDisplay
{
void HealthMonitorControlUiUpdate(List<ActiveHealthMonitorData> callBackDataList);
}
public interface INGIDisplay : IDisplay, IChillerDisplay, IDioDisplay, IFpgaDisplay, IPowerControlDisplay, IPowerMonitorDisplay, IHealthMonitorDisplay
{
}
public interface IHandleCriticalError
{
void HandleCriticalError(string message, bool shallWeStopThreads = true);
}
}

View File

@@ -0,0 +1,39 @@
// UNCLASSIFIED
/*-------------------------------------------------------------------------
RAYTHEON PROPRIETARY: THIS DOCUMENT CONTAINS DATA OR INFORMATION
PROPRIETARY TO RAYTHEON COMPANY AND IS RESTRICTED TO USE ONLY BY PERSONS
AUTHORIZED BY RAYTHEON COMPANY IN WRITING TO USE IT. DISCLOSURE TO
UNAUTHORIZED PERSONS WOULD LIKELY CAUSE SUBSTANTIAL COMPETITIVE HARM TO
RAYTHEON COMPANY'S BUSINESS POSITION. NEITHER SAID DOCUMENT NOR ITS
CONTENTS SHALL BE FURNISHED OR DISCLOSED TO OR COPIED OR USED BY PERSONS
OUTSIDE RAYTHEON COMPANY WITHOUT THE EXPRESS WRITTEN APPROVAL OF RAYTHEON
COMPANY.
THIS PROPRIETARY NOTICE IS NOT APPLICABLE IF DELIVERED TO THE U.S.
GOVERNMENT.
UNPUBLISHED WORK - COPYRIGHT RAYTHEON COMPANY.
-------------------------------------------------------------------------*/
using System;
namespace Raytheon.Common
{
/// <summary>
/// Defines an interface for specific message parsing routines
/// used in conjunction with MsgDevice
/// </summary>
public interface IMsgParser
{
/// <summary>
/// Will parse data looking for a complete message
/// </summary>
/// <param name="pData">The data to parse</param>
/// <param name="numBytesInPdata">The number of bytes in pData</param>
/// <param name="bytesToRemove">The data to remove once the parse job is complete</param>
/// <param name="messageId">The ID of the message that was parsed</param>
/// <param name="errorCode">optional error codes for a child parser to user</param>
/// <returns>true if a complete message was found, false otherwise</returns>
bool Run(IntPtr pData, uint numBytesInPdata, ref uint bytesToRemove, ref uint messageId, ref uint errorCode);
}
}

View File

@@ -0,0 +1,52 @@
// UNCLASSIFIED
/*-------------------------------------------------------------------------
RAYTHEON PROPRIETARY: THIS DOCUMENT CONTAINS DATA OR INFORMATION
PROPRIETARY TO RAYTHEON COMPANY AND IS RESTRICTED TO USE ONLY BY PERSONS
AUTHORIZED BY RAYTHEON COMPANY IN WRITING TO USE IT. DISCLOSURE TO
UNAUTHORIZED PERSONS WOULD LIKELY CAUSE SUBSTANTIAL COMPETITIVE HARM TO
RAYTHEON COMPANY'S BUSINESS POSITION. NEITHER SAID DOCUMENT NOR ITS
CONTENTS SHALL BE FURNISHED OR DISCLOSED TO OR COPIED OR USED BY PERSONS
OUTSIDE RAYTHEON COMPANY WITHOUT THE EXPRESS WRITTEN APPROVAL OF RAYTHEON
COMPANY.
THIS PROPRIETARY NOTICE IS NOT APPLICABLE IF DELIVERED TO THE U.S.
GOVERNMENT.
UNPUBLISHED WORK - COPYRIGHT RAYTHEON COMPANY.
-------------------------------------------------------------------------*/
using System;
namespace Raytheon.Common
{
/// <summary>
/// An interface to a serial port device
/// </summary>
public interface ISerialPort : IDisposable
{
/// <summary>
/// Close the communication interface
/// </summary>
void Close();
/// <summary>
///
/// </summary>
void Open();
/// <summary>
///
/// </summary>
/// <param name="dataRead"></param>
/// <returns></returns>
UInt32 Read(ref byte[] dataRead);
/// <summary>
///
/// </summary>
/// <param name="dataToWrite"></param>
void Write(byte[] dataToWrite);
void Write(String dataToWrite);
}
}

View File

@@ -0,0 +1,53 @@
// **********************************************************************************************************
// IWorkerInterface.cs
// 2/17/2023
// NGI - Next Generation Interceptor
//
// Contract No. HQ0856-21-C-0003/1022000209
//
// THIS DOCUMENT DOES NOT CONTAIN TECHNOLOGY OR TECHNICAL DATA CONTROLLED UNDER EITHER THE U.S.
// INTERNATIONAL TRAFFIC IN ARMS REGULATIONS OR THE U.S. EXPORT ADMINISTRATION REGULATIONS.
//
// RAYTHEON PROPRIETARY: THIS DOCUMENT CONTAINS DATA OR INFORMATION PROPRIETARY TO RAYTHEON
// COMPANY AND IS RESTRICTED TO USE ONLY BY PERSONS AUTHORIZED BY RAYTHEON COMPANY IN WRITING TO USE IT.
// DISCLOSURE TO UNAUTHORIZED PERSONS WOULD LIKELY CAUSE SUBSTANTIAL COMPETITIVE HARM TO RAYTHEON
// COMPANY'S BUSINESS POSITION. NEITHER SAID DOCUMENT NOR ITS CONTENTS SHALL BE FURNISHED OR DISCLOSED
// TO OR COPIED OR USED BY PERSONS OUTSIDE RAYTHEON COMPANY WITHOUT THE EXPRESS WRITTEN APPROVAL OF
// RAYTHEON COMPANY.
//
// UNPUBLISHED WORK - COPYRIGHT RAYTHEON COMPANY.
//
// DESTRUCTION NOTICE: FOR CLASSIFIED DOCUMENTS FOLLOW THE PROCEDURES IN DOD 5220.22-M,
// NATIONAL INDUSTRIAL SECURITY PROGRAM OPERATING MANUAL, FEBRUARY 2006,
// INCORPORATING CHANGE 1, MARCH 28, 2013, CHAPTER 5, SECTION 7, OR DODM 5200.01-VOLUME 3,
// DOD INFORMATION SECURITY PROGRAM: PROTECTION OF CLASSIFIED INFORMATION, ENCLOSURE 3,
// SECTION 17. FOR CONTROLLED UNCLASSIFIED INFORMATION FOLLOW THE PROCEDURES IN DODM 5200.01-VOLUME 4,
// INFORMATION SECURITY PROGRAM: CONTROLLED UNCLASSIFIED INFORMATION.
//
// CONTROLLED BY: MISSILE DEFENSE AGENCY
// CONTROLLED BY: GROUND-BASED MIDCOURSE DEFENSE PROGRAM OFFICE
// CUI CATEGORY: CTI
// DISTRIBUTION/DISSEMINATION CONTROL: F
// POC: Alex Kravchenko (1118268)
// **********************************************************************************************************
using System;
namespace Raytheon.Common
{
/// <summary>
/// An interface that defines required functions for a worker.
/// Typically a worker is invoked as a thread.
/// </summary>
public interface IWorkerInterface : IDisposable
{
/// <summary>
/// The function that is passed into the thread.
/// </summary>
void DoWork();
/// <summary>
/// Commands the worker to quit.
/// </summary>
void QuitWork();
}
}

View File

@@ -0,0 +1,215 @@
// UNCLASSIFIED
/*-------------------------------------------------------------------------
RAYTHEON PROPRIETARY: THIS DOCUMENT CONTAINS DATA OR INFORMATION
PROPRIETARY TO RAYTHEON COMPANY AND IS RESTRICTED TO USE ONLY BY PERSONS
AUTHORIZED BY RAYTHEON COMPANY IN WRITING TO USE IT. DISCLOSURE TO
UNAUTHORIZED PERSONS WOULD LIKELY CAUSE SUBSTANTIAL COMPETITIVE HARM TO
RAYTHEON COMPANY'S BUSINESS POSITION. NEITHER SAID DOCUMENT NOR ITS
CONTENTS SHALL BE FURNISHED OR DISCLOSED TO OR COPIED OR USED BY PERSONS
OUTSIDE RAYTHEON COMPANY WITHOUT THE EXPRESS WRITTEN APPROVAL OF RAYTHEON
COMPANY.
THIS PROPRIETARY NOTICE IS NOT APPLICABLE IF DELIVERED TO THE U.S.
GOVERNMENT.
UNPUBLISHED WORK - COPYRIGHT RAYTHEON COMPANY.
-------------------------------------------------------------------------*/
using System;
using System.Threading;
namespace Raytheon.Common
{
/// <summary>
/// Base class for handling incoming messages
/// </summary>
public abstract class MsgDevice : IDisposable
{
/// <summary>
/// A callback def for a completed message
/// </summary>
/// <param name="msgId"></param>
/// <param name="pData"></param>
/// <param name="numBytes"></param>
/// <param name="errorCode"></param>
unsafe public delegate void CompleteMessageCallback(uint msgId, IntPtr pData, uint numBytes, uint errorCode);
private DataBuffer _dataBuffer;
private AutoResetEvent _dataInBufferEvent;
private IWorkerInterface _msgProcessorWorker;
private bool _isProcessorThreadRunning;
private Thread _msgProcessorThread;
/// <summary>
/// The constructor
/// </summary>
/// <param name="msgParser"></param>
/// <param name="bufferSize"></param>
public MsgDevice(IMsgParser msgParser, uint bufferSize)
{
try
{
_isProcessorThreadRunning = false;
_dataBuffer = new DataBuffer(bufferSize);
_dataInBufferEvent = new AutoResetEvent(false);
_msgProcessorWorker = new MsgProcessorWorker(msgParser, ref _dataBuffer, ref _dataInBufferEvent);
_msgProcessorThread = new Thread(_msgProcessorWorker.DoWork);
}
catch (Exception)
{
throw;
}
}
/// <summary>
/// The finalizer
/// </summary>
~MsgDevice()
{
Dispose(false);
}
/// <summary>
/// The public dispose function. Necessary for commanding threads to quit
/// </summary>
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
/// <summary>
/// Add data to the buffer
/// </summary>
/// <param name="data">The data to add</param>
/// <param name="numBytes">the number of bytes to add</param>
protected void AddToBuffer(byte[] data, uint numBytes)
{
try
{
_dataBuffer.Add(data, numBytes);
_dataInBufferEvent.Set();
}
catch (Exception)
{
throw;
}
}
/// <summary>
/// Clear all data from the buffer
/// </summary>
protected void ClearBuffer()
{
try
{
_dataBuffer.RemoveAll();
}
catch (Exception)
{
throw;
}
}
/// <summary>
/// The local dispose function. Necessary for commanding threads to quit
/// </summary>
/// <param name="disposing"></param>
protected virtual void Dispose(bool disposing)
{
if (disposing)
{
try
{
_msgProcessorWorker.QuitWork();
Thread.Sleep(500);
_msgProcessorThread.Abort();
if (_msgProcessorThread.IsAlive)
{
_msgProcessorThread.Join();
}
_dataInBufferEvent.Dispose();
_msgProcessorWorker.Dispose();
_dataBuffer.Dispose();
}
catch (Exception err)
{
ErrorLogger.Instance().Write(err.Message + "\r\n" + err.StackTrace);
}
}
}
/// <summary>
/// Run the message processor thread
/// </summary>
protected void RunThread()
{
try
{
_msgProcessorThread.Start();
}
catch (Exception)
{
throw;
}
}
/// <summary>
/// Set the callback that will be invoked when a complete message is parsed out
/// </summary>
/// <param name="callback">The callback function</param>
protected void SetCompleteMessageCallback(CompleteMessageCallback callback)
{
try
{
((MsgProcessorWorker)_msgProcessorWorker).SetCallback(callback);
// now that the callback is set, we can run the thread
if (_isProcessorThreadRunning == false)
{
_msgProcessorThread.Start();
_isProcessorThreadRunning = true;
}
}
catch (Exception)
{
throw;
}
}
/// <summary>
/// Stop the message processor thread
/// </summary>
protected void QuitThread()
{
try
{
_msgProcessorWorker.QuitWork();
if (_msgProcessorThread.IsAlive)
{
_msgProcessorThread.Join();
}
}
catch (Exception)
{
throw;
}
}
/// <summary>
/// abstract function for the children to implement
/// </summary>
/// <param name="data">The data to add</param>
/// <param name="numBytes">The number of bytes to add</param>
public abstract void AddData(byte[] data, uint numBytes);
}
}

View File

@@ -0,0 +1,227 @@
// UNCLASSIFIED
/*-------------------------------------------------------------------------
RAYTHEON PROPRIETARY: THIS DOCUMENT CONTAINS DATA OR INFORMATION
PROPRIETARY TO RAYTHEON COMPANY AND IS RESTRICTED TO USE ONLY BY PERSONS
AUTHORIZED BY RAYTHEON COMPANY IN WRITING TO USE IT. DISCLOSURE TO
UNAUTHORIZED PERSONS WOULD LIKELY CAUSE SUBSTANTIAL COMPETITIVE HARM TO
RAYTHEON COMPANY'S BUSINESS POSITION. NEITHER SAID DOCUMENT NOR ITS
CONTENTS SHALL BE FURNISHED OR DISCLOSED TO OR COPIED OR USED BY PERSONS
OUTSIDE RAYTHEON COMPANY WITHOUT THE EXPRESS WRITTEN APPROVAL OF RAYTHEON
COMPANY.
THIS PROPRIETARY NOTICE IS NOT APPLICABLE IF DELIVERED TO THE U.S.
GOVERNMENT.
UNPUBLISHED WORK - COPYRIGHT RAYTHEON COMPANY.
-------------------------------------------------------------------------*/
using System;
using System.Threading;
using System.Collections.Generic;
namespace Raytheon.Common
{
/// <summary>
/// Singleton for holding onto message objects
/// </summary>
public class AutomationRxMsgBuffer
{
// class variables
private static AutomationRxMsgBuffer _AutomationRxMsgBufferInstance;
private static object _syncObj = new object();
private Dictionary<uint, List<AutomationMessage>> _msgList;
private Dictionary<uint, AutoResetEvent> _receivedMsgEvents;
private List<uint> _msgIds;
/// <summary>
/// The way to get access to this singleton
/// </summary>
/// <returns>the instance to this class</returns>
public static AutomationRxMsgBuffer Instance(List<uint> msgIds = null)
{
if (_AutomationRxMsgBufferInstance == null)
{
_AutomationRxMsgBufferInstance = new AutomationRxMsgBuffer(msgIds);
}
return _AutomationRxMsgBufferInstance;
}
/// <summary>
/// Add a message to this buffer
/// </summary>
/// <param name="msg">The message to add</param>
/// <param name="shouldWeDeleteOthers">flag for if the other messages of this type should be deleted from the buffer</param>
public void AddMsg(AutomationMessage msg, bool shouldWeDeleteOthers = true)
{
lock (_syncObj)
{
uint msgId = msg.GetMessageId();
if (shouldWeDeleteOthers == true)
{
ClearList(msgId);
}
if (_msgList.ContainsKey(msgId) == false)
{
_msgList[msgId] = new List<AutomationMessage>();
}
_msgList[msgId].Add(msg);
_receivedMsgEvents[msgId].Set();
}
}
/// <summary>
/// Remove all messages from the buffer
/// </summary>
public void ClearAllMsgs()
{
lock (_syncObj)
{
foreach (uint id in _msgList.Keys)
{
ClearList(id);
}
}
}
/// <summary>
/// Remove all messages of the command type from the buffer
/// </summary>
/// <param name="id">The message id to remove</param>
public void ClearList(uint id)
{
lock (_syncObj)
{
if (_msgList.ContainsKey(id) == true)
{
_msgList[id].Clear();
_msgList.Remove(id);
}
}
}
/// <summary>
/// Gets the oldest message in the buffer
/// </summary>
/// <param name="id">The id of the message to get</param>
/// <returns>The oldest message in the buffer</returns>
public AutomationMessage GetOldestMessage(uint id)
{
lock (_syncObj)
{
if (_msgList.ContainsKey(id))
{
List<AutomationMessage> list = _msgList[id];
AutomationMessage oldestMsg = list[0];
list.RemoveAt(0);
return oldestMsg;
}
else
{
throw new Exception("no message exists with id: " + id.ToString());
}
}
}
/// <summary>
/// Gets the most recent message from the buffer
/// </summary>
/// <param name="id">The id of the message to get</param>
/// <param name="shouldWeDeleteOthers">flag controlling if the other messages of this type should be deleted</param>
/// <returns>The message</returns>
public AutomationMessage GetNewestMessage(uint id, bool shouldWeDeleteOthers = true)
{
lock (_syncObj)
{
if (_msgList.ContainsKey(id))
{
List<AutomationMessage> list = _msgList[id];
AutomationMessage newestMsg = list[list.Count - 1];
list.RemoveAt(list.Count - 1);
if (shouldWeDeleteOthers == true)
{
ClearList(id);
}
return newestMsg;
}
else
{
throw new Exception("no message exists with id: " + id.ToString());
}
}
}
/// <summary>
/// Get the number of messages of this type in the buffer
/// </summary>
/// <param name="id">The id of the message to get</param>
/// <returns>the number of messages of this type in the buffer</returns>
public int GetNumMsgsInQueue(uint id)
{
lock (_syncObj)
{
if (_msgList.ContainsKey(id) == true)
{
return _msgList[id].Count;
}
else
{
return 0;
}
}
}
/// <summary>
///
/// </summary>
/// <param name="id"></param>
public void ResetRxEvent(uint id)
{
lock (_syncObj)
{
_receivedMsgEvents[id].Reset();
}
}
/// <summary>
/// Wait for a message to get added to the buffer
/// </summary>
/// <param name="id">The message id to wait for</param>
/// <param name="timeoutMs">The amount of time in ms to wait</param>
/// <returns>true if the message arrived, false if it did not</returns>
public bool WaitForRspMsg(uint id, int timeoutMs)
{
return _receivedMsgEvents[id].WaitOne(timeoutMs);
}
/// <summary>
/// The constructor
/// </summary>
private AutomationRxMsgBuffer(List<uint> msgIds)
{
_msgList = new Dictionary<uint, List<AutomationMessage>>();
_msgIds = msgIds;
// create an event for each msg.
_receivedMsgEvents = new Dictionary<uint, AutoResetEvent>();
foreach (uint id in _msgIds)
{
_receivedMsgEvents[id] = new AutoResetEvent(false);
}
}
}
}

View File

@@ -0,0 +1,28 @@
// UNCLASSIFIED
/*-------------------------------------------------------------------------
RAYTHEON PROPRIETARY: THIS DOCUMENT CONTAINS DATA OR INFORMATION
PROPRIETARY TO RAYTHEON COMPANY AND IS RESTRICTED TO USE ONLY BY PERSONS
AUTHORIZED BY RAYTHEON COMPANY IN WRITING TO USE IT. DISCLOSURE TO
UNAUTHORIZED PERSONS WOULD LIKELY CAUSE SUBSTANTIAL COMPETITIVE HARM TO
RAYTHEON COMPANY'S BUSINESS POSITION. NEITHER SAID DOCUMENT NOR ITS
CONTENTS SHALL BE FURNISHED OR DISCLOSED TO OR COPIED OR USED BY PERSONS
OUTSIDE RAYTHEON COMPANY WITHOUT THE EXPRESS WRITTEN APPROVAL OF RAYTHEON
COMPANY.
THIS PROPRIETARY NOTICE IS NOT APPLICABLE IF DELIVERED TO THE U.S.
GOVERNMENT.
UNPUBLISHED WORK - COPYRIGHT RAYTHEON COMPANY.
-------------------------------------------------------------------------*/
namespace Raytheon.Common
{
/// <summary>
/// A spot to hold application constants
/// </summary>
public static class Constants
{
public const string InstrumentConfigFolder = "InstrumentConfig";
}
}

View File

@@ -0,0 +1,324 @@
// UNCLASSIFIED
/*-------------------------------------------------------------------------
RAYTHEON PROPRIETARY: THIS DOCUMENT CONTAINS DATA OR INFORMATION
PROPRIETARY TO RAYTHEON COMPANY AND IS RESTRICTED TO USE ONLY BY PERSONS
AUTHORIZED BY RAYTHEON COMPANY IN WRITING TO USE IT. DISCLOSURE TO
UNAUTHORIZED PERSONS WOULD LIKELY CAUSE SUBSTANTIAL COMPETITIVE HARM TO
RAYTHEON COMPANY'S BUSINESS POSITION. NEITHER SAID DOCUMENT NOR ITS
CONTENTS SHALL BE FURNISHED OR DISCLOSED TO OR COPIED OR USED BY PERSONS
OUTSIDE RAYTHEON COMPANY WITHOUT THE EXPRESS WRITTEN APPROVAL OF RAYTHEON
COMPANY.
THIS PROPRIETARY NOTICE IS NOT APPLICABLE IF DELIVERED TO THE U.S.
GOVERNMENT.
UNPUBLISHED WORK - COPYRIGHT RAYTHEON COMPANY.
-------------------------------------------------------------------------*/
using System;
using System.Runtime.InteropServices;
namespace Raytheon.Common
{
/// <summary>
/// this class is a container. It acts like an array that allows bytes to be removed from its
/// front. When bytes are removed, the beginning of the buffer moves to the byte following
/// those which were removed. A typical use of this is to AddData(), then use CheckOutStartOfData()/CheckInStartOfData to get
/// a pointer to the data and the amount of bytes that the pointer points to.
/// </summary>
public class DataBuffer: IDisposable
{
#region PrivateClassMembers
private unsafe byte[] _buffer;
private uint _endOfDataIndex; // index of last used byte
private uint _startOfDataIndex = uint.MaxValue; // index of first used byte, MaxValue means that buffer is empty
private uint _startOfCheckedOutDataIndex = uint.MaxValue; // index of first used byte, MaxValue means that buffer is empty
private static object _syncObj = new Object();
private IntPtr _pStartOfBuffer;
private IntPtr _pStartOfCheckedOutData;
private GCHandle _pinnedArray;
#endregion
#region PublicFuctions
/// <summary>
/// The constructor which allocates a byte array and pins it so we can return byte*s in StartOfData()
/// </summary>
/// <param name="bufferSize">The number of bytes in the data buffer</param>
public DataBuffer(uint bufferSize)
{
_buffer = new byte[bufferSize];
_pinnedArray = GCHandle.Alloc(_buffer, GCHandleType.Pinned);
_pStartOfBuffer = _pinnedArray.AddrOfPinnedObject();
_pStartOfCheckedOutData = IntPtr.Zero;
}
/// <summary>
/// The finalizer
/// </summary>
~DataBuffer()
{
Dispose(false);
}
/// <summary>
/// adds bytes to the buffer
/// throws exception if requesting to add more bytes than entire buffer will hold.
/// throws an exception if data is checked out and this call attempts to overwrite the checked out data
/// </summary>
/// <param name="data">array from which to add bytes to buffer</param>
/// <param name="numBytesToAdd"># if bytes from array to add to buffer</param>
public void Add(byte[] data, uint numBytesToAdd)
{
// get exclusive access to array, indexes...
lock (_syncObj)
{
uint numBytesCurrentlyUsed = BytesUsed;
// not enough room in entire buffer?
if (numBytesToAdd > (_buffer.Length - numBytesCurrentlyUsed))
{
throw new Exception("DataBuffer::Add() - Not enough room in buffer for data - need to increase size of buffer");
}
// empty buffer?
if (_startOfDataIndex == UInt32.MaxValue)
{
Array.Copy(data, _buffer, numBytesToAdd);
_startOfDataIndex = 0;
_endOfDataIndex = numBytesToAdd - 1;
}
else // not empty
{
// not enough room at end?
if (numBytesToAdd > (_buffer.Length - _endOfDataIndex - 1))
{
// make sure not overwritting checked out data
ulong afterShiftEndOfDataAddy = (ulong)_pStartOfBuffer + numBytesCurrentlyUsed - 1 + numBytesToAdd;
if (_pStartOfCheckedOutData != IntPtr.Zero &&
afterShiftEndOfDataAddy >= (ulong)_pStartOfCheckedOutData)
{
throw new Exception("DataBuffer::Add() - attempting to overwrite data that is checked out (when shifting data to beginning)");
}
// shuffle to front of buffer
Array.Copy(_buffer, _startOfDataIndex, _buffer, 0, BytesUsed);
_endOfDataIndex = BytesUsed - 1;
_startOfDataIndex = 0;
}
else if (_pStartOfCheckedOutData != IntPtr.Zero)
{
// make sure not trying to overwrite data when it is checked out
ulong endOfDataAddress = (ulong)_pStartOfBuffer + _endOfDataIndex;
if (endOfDataAddress < (ulong)_pStartOfCheckedOutData &&
endOfDataAddress + numBytesToAdd >= (ulong)_pStartOfCheckedOutData)
{
throw new Exception("DataBuffer::Add() - attempting to overwrite data that is checked out");
}
}
Array.Copy(data, 0, _buffer, _endOfDataIndex + 1, numBytesToAdd);
_endOfDataIndex += numBytesToAdd;
}
}
}
/// <summary>
/// returns # of bytes used in buffer
/// </summary>
public uint BytesUsed
{
get
{
lock (_syncObj)
{
// is buffer empty?
if (_startOfDataIndex == uint.MaxValue)
{
return 0;
}
else
{
return _endOfDataIndex - _startOfDataIndex + 1;
}
}
}
}
/// <summary>
/// Checks in the data. This should be used after a call to CheckOutStartOfData()
/// </summary>
public void CheckInStartOfData()
{
lock (_syncObj)
{
_pStartOfCheckedOutData = IntPtr.Zero;
}
}
/// <summary>
/// This returns a pointer to the start of the new data
/// </summary>
/// <param name="numBytesInReturnedBuffer">The number of bytes that the returned pointer contains</param>
/// <returns>A pointer to the data</returns>
public IntPtr CheckOutStartOfData(ref uint numBytesInReturnedBuffer)
{
lock (_syncObj)
{
// hold onto the start index of the checked out data
_startOfCheckedOutDataIndex = _startOfDataIndex;
numBytesInReturnedBuffer = 0;
// if nothing is in the buffer, _startOfCheckedOutDataIndex will be MaxValue
if (_startOfCheckedOutDataIndex != uint.MaxValue)
{
// wrap around condition
if (_endOfDataIndex < _startOfCheckedOutDataIndex)
{
// set the number of bytes from start of data to the end of the buffer
numBytesInReturnedBuffer = (uint)_buffer.Length - _startOfCheckedOutDataIndex + 1;
}
else
{
numBytesInReturnedBuffer = _endOfDataIndex - _startOfCheckedOutDataIndex + 1;
}
}
_pStartOfCheckedOutData = IntPtr.Add(_pStartOfBuffer, (int)_startOfCheckedOutDataIndex);
return _pStartOfCheckedOutData;
}
}
/// <summary>
/// Copies data into specified array from buffer
/// Throws exception if asking to copy more bytes than buffer contains
/// </summary>
/// <param name="data">array into which to copy data from buffer</param>
/// <param name="numBytesToCopy"># bytes to copy from buffer to array</param>
public void Copy(ref byte[] data, uint numBytesToCopy)
{
lock (_syncObj)
{
// asking to copy more bytes than we have?
if (numBytesToCopy > BytesUsed)
{
throw new Exception("DataBuffer::Copy() - Asking to copy more bytes than exist in buffer");
}
Array.Copy(_buffer, _startOfDataIndex, data, 0, numBytesToCopy);
}
}
/// <summary>
/// Disposes of resources
/// </summary>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1063:ImplementIDisposableCorrectly")]
public void Dispose()
{
try
{
lock (_syncObj)
{
Dispose(true);
GC.SuppressFinalize(this);
}
}
catch (Exception err)
{
try
{
ErrorLogger.Instance().Write(err.Message + "\r\n" + err.StackTrace);
}
catch (Exception)
{
//Do not rethrow. Exception from error logger that has already been garbage collected
}
}
}
/// <summary>
/// Gets the size of the buffer
/// </summary>
/// <returns>returns the number of bytes of the buffer.</returns>
public uint GetSize()
{
lock (_syncObj)
{
return (uint)(_buffer.Length);
}
}
/// <summary>
/// Removes data from the buffer
/// </summary>
/// <param name="numBytesToRemove">The number of bytes to remove</param>
public void Remove(uint numBytesToRemove)
{
lock (_syncObj)
{
// asking to remove more bytes than we have?
if (numBytesToRemove > BytesUsed)
{
throw new Exception("DataBuffer::Remove() - Requested to remove more bytes than exist in buffer");
}
// remove all bytes?
if (numBytesToRemove == BytesUsed)
{
_startOfDataIndex = UInt32.MaxValue;
// all of the data is gone, need to set the _pStartOfCheckedOutData back to zero to prevent a race condition between adding data and the host checking the data back in
_pStartOfCheckedOutData = IntPtr.Zero;
}
else
{
_startOfDataIndex += numBytesToRemove;
}
}
}
/// <summary>
/// Removes all data from the buffer
/// </summary>
public void RemoveAll()
{
lock (_syncObj)
{
Remove(BytesUsed);
}
}
/// <summary>
/// Disposes of resources
/// </summary>
/// <param name="disposing"></param>
protected virtual void Dispose(bool disposing)
{
try
{
if (disposing)
{
_pinnedArray.Free();
}
}
catch (Exception err)
{
try
{
ErrorLogger.Instance().Write(err.Message + "\r\n" + err.StackTrace);
}
catch (Exception)
{
//Do not rethrow. Exception from error logger that has already been garbage collected
}
}
}
#endregion
}
}

View File

@@ -0,0 +1,123 @@
// UNCLASSIFIED
/*-------------------------------------------------------------------------
RAYTHEON PROPRIETARY: THIS DOCUMENT CONTAINS DATA OR INFORMATION
PROPRIETARY TO RAYTHEON COMPANY AND IS RESTRICTED TO USE ONLY BY PERSONS
AUTHORIZED BY RAYTHEON COMPANY IN WRITING TO USE IT. DISCLOSURE TO
UNAUTHORIZED PERSONS WOULD LIKELY CAUSE SUBSTANTIAL COMPETITIVE HARM TO
RAYTHEON COMPANY'S BUSINESS POSITION. NEITHER SAID DOCUMENT NOR ITS
CONTENTS SHALL BE FURNISHED OR DISCLOSED TO OR COPIED OR USED BY PERSONS
OUTSIDE RAYTHEON COMPANY WITHOUT THE EXPRESS WRITTEN APPROVAL OF RAYTHEON
COMPANY.
THIS PROPRIETARY NOTICE IS NOT APPLICABLE IF DELIVERED TO THE U.S.
GOVERNMENT.
UNPUBLISHED WORK - COPYRIGHT RAYTHEON COMPANY.
-------------------------------------------------------------------------*/
using System;
using System.IO;
using NLog;
using System.Reflection;
namespace Raytheon.Common
{
/// <summary>
/// Singleton for logging debug information and errors.
/// </summary>
public class ErrorLogger : IDisposable
{
#region PublicClassMembers
/// <summary>
/// Enum for tagging the logged data.
/// </summary>
public enum LogLevel
{
/// <summary>
/// (Ordinal = 0) : Most verbose level. Used for development and seldom enabled in production.
/// </summary>
TRACE,
/// <summary>
/// (Ordinal = 1) : Debugging the application behavior from internal events of interest.
/// </summary>
DEBUG,
/// <summary>
/// An informational log statement.
/// (Ordinal = 2) : Information that highlights progress or application lifetime events.
/// </summary>
INFO,
/// <summary>
/// (Ordinal = 3) : Warnings about validation issues or temporary failures that can be recovered.
/// </summary>
WARN,
/// <summary>
/// (Ordinal = 4) : Errors where functionality has failed or <see cref="System.Exception"/> have been caught.
/// an error log statement.
/// </summary>
ERROR,
/// <summary>
/// (Ordinal = 5) : Most critical level. Application is about to abort.
/// </summary>
FATAL
}
private readonly ILogger _logger;
#endregion
#region PrivateClassMembers
private static ErrorLogger _errorLoggerInstance;
#endregion
#region PublicClassFunctions
/// <summary>
/// Getter for this singleton.
/// </summary>
/// <param name="loggername">File location for Log.</param>
/// <returns>The instance of this class.</returns>
public static ErrorLogger Instance(string loggername = "CTS")
{
if (_errorLoggerInstance == null)
{
_errorLoggerInstance = new ErrorLogger(loggername);
}
return _errorLoggerInstance;
}
/// <summary>
///
/// </summary>
/// <param name="logDestination">The logger destination</param>
/// <param name="logname">The location of the file to write to.</param>
/// <param name="form"></param>
private ErrorLogger(string logname)
{
_logger = LogManager.GetLogger(logname);
if (LogManager.Configuration == null)
{
var assemblyFolder = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
//TODO: Unhandled exception if no nlog.config
LogManager.Configuration = new NLog.Config.XmlLoggingConfiguration(assemblyFolder + "\\nlog.config");
}
}
/// <summary>
/// Write data to the log file.
/// </summary>
/// <param name="message">The data to write.</param>
public void Write(string message, LogLevel logLevel = LogLevel.ERROR)
{
_logger.Log(NLog.LogLevel.FromOrdinal((int)logLevel), message);
}
public void Dispose()
{
}
#endregion
}
}

View File

@@ -0,0 +1,450 @@
// UNCLASSIFIED
/*-------------------------------------------------------------------------
RAYTHEON PROPRIETARY: THIS DOCUMENT CONTAINS DATA OR INFORMATION
PROPRIETARY TO RAYTHEON COMPANY AND IS RESTRICTED TO USE ONLY BY PERSONS
AUTHORIZED BY RAYTHEON COMPANY IN WRITING TO USE IT. DISCLOSURE TO
UNAUTHORIZED PERSONS WOULD LIKELY CAUSE SUBSTANTIAL COMPETITIVE HARM TO
RAYTHEON COMPANY'S BUSINESS POSITION. NEITHER SAID DOCUMENT NOR ITS
CONTENTS SHALL BE FURNISHED OR DISCLOSED TO OR COPIED OR USED BY PERSONS
OUTSIDE RAYTHEON COMPANY WITHOUT THE EXPRESS WRITTEN APPROVAL OF RAYTHEON
COMPANY.
THIS PROPRIETARY NOTICE IS NOT APPLICABLE IF DELIVERED TO THE U.S.
GOVERNMENT.
UNPUBLISHED WORK - COPYRIGHT RAYTHEON COMPANY.
-------------------------------------------------------------------------*/
using Microsoft.Office.Interop.Excel;
using System;
using System.Collections.Generic;
using System.IO;
using System.Runtime.InteropServices;
namespace Raytheon.Common
{
/// <summary>
/// An interface to an excel workbook
/// </summary>
public class ExcelReader : IDisposable
{
#region PublicClassMembers
public struct CellRowInfo
{
public int _colNumber;
public string _cellValue;
internal CellRowInfo(int colNumber, string cellValue)
{
_colNumber = colNumber;
_cellValue = cellValue;
}
};
#endregion
#region PrivateClassMembers
private readonly string _fileName;
private Application _excelApp;
private _Workbook _excelWorkBook;
#endregion
#region PublicFuctions
/// <summary>
/// The constructor.
/// </summary>
/// <param name="fileName">The excel file name (full path)</param>
public ExcelReader(string fileName)
{
_fileName = System.IO.Path.GetFullPath(fileName);
bool doesFileExist = File.Exists(_fileName);
if (doesFileExist == false)
{
throw new Exception("ExcelReader::ExcelReader() - File: " + fileName + " Does not exist");
}
//Start Excel and get Application object.
_excelApp = new Application();
_excelApp.Visible = false;
_excelWorkBook = _excelApp.Workbooks.Open(_fileName);
}
/// <summary>
///
/// </summary>
~ExcelReader()
{
Dispose(false);
}
/// <summary>
///
/// </summary>
public void Dispose()
{
try
{
Dispose(true);
GC.SuppressFinalize(this);
}
catch (Exception err)
{
try
{
ErrorLogger.Instance().Write(err.Message + "\r\n" + err.StackTrace);
}
catch (Exception)
{
//Do not rethrow. Exception from error logger that has already been garbage collected
}
}
}
/// <summary>
///
/// </summary>
/// <param name="sheetName"></param>
/// <param name="rows"></param>
public void AddRows(string sheetName, List<List<ExcelReader.CellRowInfo>> rows)
{
_Worksheet sheet = null;
Range excelRange = null;
try
{
sheet = _excelWorkBook.Sheets[sheetName];
sheet.Select(Type.Missing);
excelRange = sheet.UsedRange;
int rowCount = excelRange.Rows.Count;
int colCount = excelRange.Columns.Count;
int newRowNumber = rowCount + 1;
// insert the new rows
string insertCommand = newRowNumber.ToString() + ":" + (newRowNumber + rows.Count).ToString();
sheet.Range[insertCommand].Insert();
// fill the cell values
foreach (List<ExcelReader.CellRowInfo> cellInfoList in rows)
{
foreach (CellRowInfo cellInfo in cellInfoList)
{
Range cell = sheet.Cells[newRowNumber, cellInfo._colNumber];
cell.Value = cellInfo._cellValue;
}
newRowNumber++;
}
}
catch (Exception)
{
throw;
}
finally
{
Marshal.ReleaseComObject(excelRange);
Marshal.ReleaseComObject(sheet);
}
}
/// <summary>
///
/// </summary>
/// <param name="sheetName"></param>
/// <param name="rowValues"></param>
/*public void AddRow(string sheetName, List<CellRowInfo> rowValues)
{
_Worksheet sheet = null;
Range excelRange = null;
try
{
sheet = _excelWorkBook.Sheets[sheetName];
sheet.Select(Type.Missing);
excelRange = sheet.UsedRange;
int rowCount = excelRange.Rows.Count;
int colCount = excelRange.Columns.Count;
int newRowNumber = rowCount + 1;
// insert the new row
sheet.Rows[rowCount].Insert(newRowNumber);
// set each cell to empty string
int col = 1;
while (col < colCount)
{
Range cell = sheet.Cells[newRowNumber, col];
cell.Value = "";
col++;
}
// fill the cell values
foreach (CellRowInfo cellInfo in rowValues)
{
Range cell = sheet.Cells[newRowNumber, cellInfo.colNumber];
cell.Value = cellInfo.cellValue;
col++;
}
}
catch (Exception e)
{
throw;
}
finally
{
Marshal.ReleaseComObject(excelRange);
Marshal.ReleaseComObject(sheet);
}
}
/// <summary>
///
/// </summary>
/// <param name="sheetName"></param>
/// <param name="rowValues"></param>
public void AddRow(string sheetName, List<string> rowValues)
{
_Worksheet sheet = null;
Range excelRange = null;
try
{
sheet = _excelWorkBook.Sheets[sheetName];
sheet.Select(Type.Missing);
excelRange = sheet.UsedRange;
int rowCount = excelRange.Rows.Count;
int colCount = excelRange.Columns.Count;
int newRowNumber = rowCount + 1;
// insert the new row
sheet.Rows[rowCount].Insert(newRowNumber);
// set each cell to empty string
int col = 1;
while (col < colCount)
{
Range cell = sheet.Cells[newRowNumber, col];
cell.Value = "";
col++;
}
// fill the cell values
foreach (string cellValue in rowValues)
{
Range cell = sheet.Cells[newRowNumber, col];
cell.Value = cellValue;
col++;
}
}
catch (Exception e)
{
throw;
}
finally
{
Marshal.ReleaseComObject(excelRange);
Marshal.ReleaseComObject(sheet);
}
}*/
public void ColorCell(string sheetName, int row, int col, System.Drawing.Color color)
{
_Worksheet sheet = null;
Range excelRange = null;
try
{
if (row < 1 || col < 1)
{
throw new Exception("ExcelReader::ColorCell() - row and col inputs must be greater than 0");
}
sheet = _excelWorkBook.Sheets[sheetName];
sheet.Select(Type.Missing);
excelRange = sheet.UsedRange;
Range cell = sheet.Cells[row, col];
cell.Interior.Color = color;
}
catch (Exception)
{
throw;
}
finally
{
Marshal.ReleaseComObject(excelRange);
Marshal.ReleaseComObject(sheet);
}
}
/// <summary>
///
/// </summary>
/// <returns></returns>
public List<string> ReadAllSheetNames()
{
List<string> sheetList = new List<string>();
foreach (_Worksheet temp in _excelWorkBook.Sheets)
{
sheetList.Add(temp.Name.ToUpper());
}
return sheetList;
}
/// <summary>
///
/// </summary>
/// <param name="sheetName"></param>
/// <param name="startingRow"></param>
/// <param name="startingCol"></param>
/// <returns></returns>
public string ReadAllRows(string sheetName, int startingRow, int startingCol)
{
_Worksheet sheet = null;
Range excelRange = null;
try
{
ErrorLogger.Instance().Write("ExcelReader::ReadAllRows() - for sheet " + sheetName, ErrorLogger.LogLevel.INFO);
if (startingRow < 1 || startingCol < 1)
{
throw new Exception("ExcelReader::ReadAllRows() - startingRow and startingCol inputs must be greater than 0");
}
// check to see if the requested sheet exists.
bool doesSheetExist = false;
foreach (_Worksheet temp in _excelWorkBook.Sheets)
{
if (temp.Name.ToUpper() == sheetName.ToUpper())
{
doesSheetExist = true;
break;
}
}
// give a nice error if it doesnt exist
if (doesSheetExist == false)
{
throw new Exception("ExcelReader::ReadAllRows() - sheet: " + sheetName + " does not exist in file: " + _fileName);
}
sheet = _excelWorkBook.Sheets[sheetName];
sheet.Select(Type.Missing);
excelRange = sheet.UsedRange;
string allRows = "";
int rowCount = excelRange.Rows.Count;
int colCount = excelRange.Columns.Count;
for (int currentRowIndex = startingRow; currentRowIndex <= rowCount; currentRowIndex++)
{
string currentRowData = "";
for (int currentColIndex = startingCol; currentColIndex <= colCount; currentColIndex++)
{
if (excelRange.Cells[currentRowIndex, currentColIndex] != null)
{
if (excelRange.Cells[currentRowIndex, currentColIndex].Value2 == null)
{
currentRowData += ",";
}
else
{
string cellValue = excelRange.Cells[currentRowIndex, currentColIndex].Value2.ToString();
cellValue = cellValue.Replace(',', ' ');
currentRowData += cellValue + ",";
}
}
}
// remove any newlines
currentRowData = currentRowData.Replace('\n', ' ');
// strip off the last comma and add the newline
currentRowData = currentRowData.TrimEnd(',');
allRows += currentRowData + "\n";
}
// remove the \n at the end of the string
allRows = allRows.TrimEnd('\n');
return allRows;
}
catch (Exception)
{
throw;
}
finally
{
if (excelRange != null)
{
Marshal.ReleaseComObject(excelRange);
}
if (sheet != null)
{
Marshal.ReleaseComObject(sheet);
}
}
}
/// <summary>
///
/// </summary>
/// <param name="fileName"></param>
public void SaveAs(string fileName)
{
_excelWorkBook.SaveAs(fileName);
}
/// <summary>
///
/// </summary>
/// <param name="disposing"></param>
protected virtual void Dispose(bool disposing)
{
try
{
if (disposing)
{
//close and release
if (_excelWorkBook != null)
{
_excelWorkBook.Close();
Marshal.ReleaseComObject(_excelWorkBook);
}
//quit and release
if (_excelApp != null)
{
_excelApp.Quit();
Marshal.ReleaseComObject(_excelApp);
}
}
}
catch (Exception err)
{
try
{
ErrorLogger.Instance().Write(err.Message + "\r\n" + err.StackTrace);
}
catch (Exception)
{
//Do not rethrow. Exception from error logger that has already been garbage collected
}
}
}
#endregion
}
}

View File

@@ -0,0 +1,183 @@
// UNCLASSIFIED
/*-------------------------------------------------------------------------
RAYTHEON PROPRIETARY: THIS DOCUMENT CONTAINS DATA OR INFORMATION
PROPRIETARY TO RAYTHEON COMPANY AND IS RESTRICTED TO USE ONLY BY PERSONS
AUTHORIZED BY RAYTHEON COMPANY IN WRITING TO USE IT. DISCLOSURE TO
UNAUTHORIZED PERSONS WOULD LIKELY CAUSE SUBSTANTIAL COMPETITIVE HARM TO
RAYTHEON COMPANY'S BUSINESS POSITION. NEITHER SAID DOCUMENT NOR ITS
CONTENTS SHALL BE FURNISHED OR DISCLOSED TO OR COPIED OR USED BY PERSONS
OUTSIDE RAYTHEON COMPANY WITHOUT THE EXPRESS WRITTEN APPROVAL OF RAYTHEON
COMPANY.
THIS PROPRIETARY NOTICE IS NOT APPLICABLE IF DELIVERED TO THE U.S.
GOVERNMENT.
UNPUBLISHED WORK - COPYRIGHT RAYTHEON COMPANY.
-------------------------------------------------------------------------*/
using System;
using System.Runtime.InteropServices;
using System.Collections.Generic;
using System.IO;
namespace Raytheon.Common
{
/// <summary>
/// Read/Write to an ini file.
/// </summary>
public class IniFile
{
#region PrivateMemberVariables
/// <summary>
///
/// </summary>
internal static class NativeMethods
{
[DllImport("kernel32.dll", CharSet = CharSet.Unicode)]
internal static extern int GetPrivateProfileString(string lpAppName, string lpKeyName, string lpDefault, string lpReturnedstring, int nSize, string lpFileName);
[DllImport("kernel32.dll", CharSet = CharSet.Unicode)]
[return: MarshalAs(UnmanagedType.Bool)]
internal static extern bool WritePrivateProfileString(string lpAppName, string lpKeyName, string line, string lpFileName);
[DllImport("kernel32.dll", CharSet = CharSet.Unicode)]
internal static extern int GetPrivateProfileSectionNames(byte[] sections, int bufferSize, string filename);
}
private readonly string _fileName;
#endregion
#region PublicFunctions
/// <summary>
/// The constructor. It will check to make sure the file exists and throw an exception it if does not
/// </summary>
/// <param name="fileName">The ini file name (path).</param>
public IniFile(string fileName)
{
_fileName = fileName;
if (File.Exists(_fileName) == false)
{
throw new Exception("IniFile::IniFile() - The file does not exist: " + _fileName);
}
}
/// <summary>
/// Reads from the ini file.
/// </summary>
/// <param name="section">The section.</param>
/// <param name="key">The key.</param>
/// <returns>The value.</returns>
public string ReadValue(string section, string key)
{
// just a swag
const int BUFFER_SIZE = 10240;
string temp = new string('\0', BUFFER_SIZE);
int numBytes = NativeMethods.GetPrivateProfileString(section, key, "", temp, BUFFER_SIZE, _fileName);
if (numBytes == 0)
{
throw new Exception("IniFile::ReadValue() - GetPrivateProfilestring returned 0 bytes for section: " + section + ", key: " + key);
}
temp = temp.TrimEnd('\0');
return temp;
}
/// <summary>
/// Reads all keys from a section of an ini file.
/// </summary>
/// <param name="section">The section.</param>
/// <returns>A list of all keys.</returns>
public List<string> ReadAllKeys(string section)
{
// just a swag
const int BUFFER_SIZE = 102400;
string temp = new string('\0', BUFFER_SIZE);
int numBytes = NativeMethods.GetPrivateProfileString(section, null, "", temp, BUFFER_SIZE, _fileName);
if (numBytes == 0)
{
List<string> keyList = new List<string>();
return keyList;
}
else
{
temp = temp.TrimEnd('\0');
List<string> keyList = new List<string>(temp.Split('\0'));
return keyList;
}
}
/// <summary>
/// Returns a list of all of the sections in the ini file.
/// </summary>
/// <returns>A list of all sections.</returns>
public List<string> ReadAllSections()
{
// just a swag
const int BUFFER_SIZE = 102040;
// allocate a 10K buffer. Should be enough to handle plenty of power systems
byte[] buffer = new byte[BUFFER_SIZE];
int numBytesReturned = NativeMethods.GetPrivateProfileSectionNames(buffer, BUFFER_SIZE, _fileName);
if (numBytesReturned == BUFFER_SIZE)
{
throw new Exception("IniFile::ReadAllSections() - returned the max buffer size. Probably have more items in config file than we can handle");
}
else if (numBytesReturned == 0)
{
throw new Exception("IniFile::ReadAllSections() - GetPrivateProfileSectionNames returned 0 bytes");
}
// convert the buffer to a string
string result = System.Text.Encoding.Unicode.GetString(buffer);
// trim the end of the string
result = result.TrimEnd('\0');
// split the string
string[] sectionListTemp = result.Split('\0');
// ass the sections to a list
List<string> sectionList = new List<string>();
for (int i = 0; i < sectionListTemp.Length; ++i)
{
sectionList.Add(sectionListTemp[i]);
}
return sectionList;
}
/// <summary>
///
/// </summary>
/// <param name="section"></param>
/// <param name="key"></param>
/// <param name="lineToWrite"></param>
public void WriteValue(string section, string key, string lineToWrite)
{
bool success = NativeMethods.WritePrivateProfileString(section, key, lineToWrite, _fileName);
if (success == false)
{
throw new Exception("IniFile::WriteValue() - WritePrivateProfileString returned false for section: " + section + ", key: " + key + " , line: " + lineToWrite);
}
}
#endregion
}
}

View File

@@ -0,0 +1,316 @@
// UNCLASSIFIED
/*-------------------------------------------------------------------------
RAYTHEON PROPRIETARY: THIS DOCUMENT CONTAINS DATA OR INFORMATION
PROPRIETARY TO RAYTHEON COMPANY AND IS RESTRICTED TO USE ONLY BY PERSONS
AUTHORIZED BY RAYTHEON COMPANY IN WRITING TO USE IT. DISCLOSURE TO
UNAUTHORIZED PERSONS WOULD LIKELY CAUSE SUBSTANTIAL COMPETITIVE HARM TO
RAYTHEON COMPANY'S BUSINESS POSITION. NEITHER SAID DOCUMENT NOR ITS
CONTENTS SHALL BE FURNISHED OR DISCLOSED TO OR COPIED OR USED BY PERSONS
OUTSIDE RAYTHEON COMPANY WITHOUT THE EXPRESS WRITTEN APPROVAL OF RAYTHEON
COMPANY.
THIS PROPRIETARY NOTICE IS NOT APPLICABLE IF DELIVERED TO THE U.S.
GOVERNMENT.
UNPUBLISHED WORK - COPYRIGHT RAYTHEON COMPANY.
-------------------------------------------------------------------------*/
using System;
using System.Collections.Generic;
using System.IO;
using System.Text.RegularExpressions;
namespace Raytheon.Common
{
/// <summary>
/// A class that reads a memory map upon construction and then serves up the fields of an entry upon request
/// </summary>
public class MemoryMap
{
#region PrivateClassMembers
public struct MemoryMapFields
{
public readonly uint _page;
public readonly uint _address;
public readonly int _startBit;
public readonly int _numBits;
public readonly uint _regDefault;
public readonly double _scaleFactor;
public MemoryMapFields(uint page, uint address, int startBit, int numBits, uint regDefault, double scaleFactor)
{
_page = page;
_address = address;
_startBit = startBit;
_numBits = numBits;
_regDefault = regDefault;
_scaleFactor = scaleFactor;
}
}
private struct BitInfo
{
public int _start;
public int _numOfBits;
}
private const string _NEWLINE = "\r\n";
private Dictionary<string, MemoryMapFields> _mapData;
private double _scaleFactor = 1.0;
#endregion
#region PrivateFuctions
/// <summary>
///
/// </summary>
/// <param name="fileLocation"></param>
/// <returns></returns>
private Dictionary<string, MemoryMapFields> CreateMemoryMapDictionary(string fileLocation)
{
Dictionary<string, MemoryMapFields> temp = new Dictionary<string, MemoryMapFields>();
//Open file for processing (read-only)
using (FileStream readStream = new FileStream(fileLocation, FileMode.Open, FileAccess.Read))
{
//Process the memmap
ProcessFile(readStream, temp);
}
return temp;
}
/// <summary>
/// Processes the memory map files into a data structure
/// </summary>
/// <param name="fs"></param>
/// <param name="memoryMap"></param>
private void ProcessFile(FileStream fs, Dictionary<string, MemoryMapFields> memoryMap)
{
uint page = 0;
uint address = 0;
uint regDefault = 0;
char[] delimit = { ' ' };
uint prevPage = 0;
uint prevAddress = 0;
uint parentRegDefault = 0;
using (StreamReader reader = new StreamReader(fs))
{
while (!reader.EndOfStream)
{
//Read a line from the file
string line = reader.ReadLine();
//Parse the line by spaces (remove empty entries)
string[] fields = line.Split(delimit, StringSplitOptions.RemoveEmptyEntries);
//If nothing to read, stop processing
if (fields.Length == 0)
{
break;
}
//Get the key (Register Name)
string key = fields[0].ToUpper();
//Check for duplicates
if (memoryMap.ContainsKey(key))
{
throw new Exception("Duplicate item found in file: " + fs.Name + ", Item key: " + key);
}
//Check if the register is a parent or child
//A child will use its parent address and gets it default value from its parent
if (line.StartsWith(" "))
{
regDefault = parentRegDefault;
page = prevPage;
address = prevAddress;
}
else
{
//Get the page number
page = ProcessPageNum(fields[1]);
//Get register address
address = ProcessDecimalHex(fields[1]);
//Get register default values
regDefault = ProcessDecimalHex(fields[5]);
//Get scale factor
_scaleFactor = ProcessScaleFactor(line);
}
//Process bits
BitInfo bitInfo = ProcessBitInfo(fields[3]);
double scaleFactor = _scaleFactor;
// parse out the default value for this child item
if (bitInfo._numOfBits < 32)
{
// clear the upper bits
int numBitsToClear = 32 - (bitInfo._start + bitInfo._numOfBits);
regDefault = regDefault << numBitsToClear;
// clear lower bits and place into position
int numBitsForPosition = bitInfo._start + numBitsToClear;
regDefault = regDefault >> numBitsForPosition;
}
else
{
parentRegDefault = regDefault;
}
memoryMap.Add(key, new MemoryMapFields(page, address, bitInfo._start, bitInfo._numOfBits, regDefault, scaleFactor));
// hold onto previous values for child items
prevPage = page;
prevAddress = address;
}
}
}
/// <summary>
///
/// </summary>
/// <param name="pageNumber"></param>
/// <returns></returns>
private uint ProcessPageNum(string pageNumber)
{
//Delimiter used to parse string
char[] delimit = { '.' };
//Array of parsed string
string[] strPageValues = pageNumber.Split(delimit);
//Convert first array element
uint value = uint.Parse(strPageValues[0]);
//Return conversion
return value;
}
/// <summary>
///
/// </summary>
/// <param name="address"></param>
/// <returns></returns>
private uint ProcessDecimalHex(string address)
{
//Delimiter used to parse string
char[] delimit = { '.' };
//Array of parsed string
string[] strValues = address.Split(delimit);
string strCombined = "";
//Address = 0.XXXX.XXXX, register values = XXXX.XXXX
if (strValues.Length == 3)
{
strCombined = strValues[1] + strValues[2];
}
else
{
strCombined = strValues[0] + strValues[1];
}
//Convert hex number to UInt
uint value = uint.Parse(strCombined, System.Globalization.NumberStyles.HexNumber);
//Return value
return value;
}
/// <summary>
///
/// </summary>
/// <param name="bits"></param>
/// <returns></returns>
private BitInfo ProcessBitInfo(string bits)
{
//Structure for bit information
BitInfo temp;
//Delimiter used to parse string
char[] delimit = { ':' };
char[] trimChar = { '(', ')' };
string trimBits = bits.Trim(trimChar);
string[] values = trimBits.Split(delimit);
if (values.Length == 2)
{
//values represents a range of bits
int start = int.Parse(values[1]);
int end = int.Parse(values[0]);
//Add one for zero offset
temp._start = start;
temp._numOfBits = end - start + 1;
}
else
{
//Only a single bit
temp._numOfBits = 1;
temp._start = int.Parse(values[0]);
}
return temp;
}
/// <summary>
///
/// </summary>
/// <param name="scaleFactor"></param>
/// <returns></returns>
private double ProcessScaleFactor(string scaleFactor)
{
const string PATTERN = @"[+-]?[0-9]{1,}\.[0-9]{1,}[e][+-]?[0-9]{1,}";
//Find Scale Factor (default = 1)
string sf = "1";
foreach (Match match in Regex.Matches(scaleFactor, PATTERN))
{
sf = match.Value;
}
double value = double.Parse(sf);
return value;
}
#endregion
#region PublicFuctions
/// <summary>
/// The constructor
/// </summary>
/// <param name="memMapLocation">The memory map file</param>
public MemoryMap(string memMapLocation)
{
_mapData = CreateMemoryMapDictionary(memMapLocation);
}
/// <summary>
///
/// </summary>
/// <param name="registerName">The name of the register</param>
/// <returns></returns>
public MemoryMapFields GetRegisterInfoByString(string registerName)
{
if (_mapData.ContainsKey(registerName.ToUpper()) == false)
{
throw new Exception("The requested register: " + registerName + " is not in the memory map");
}
return _mapData[registerName.ToUpper()];
}
#endregion
}
}

View File

@@ -0,0 +1,418 @@
// UNCLASSIFIED
/*-------------------------------------------------------------------------
RAYTHEON PROPRIETARY: THIS DOCUMENT CONTAINS DATA OR INFORMATION
PROPRIETARY TO RAYTHEON COMPANY AND IS RESTRICTED TO USE ONLY BY PERSONS
AUTHORIZED BY RAYTHEON COMPANY IN WRITING TO USE IT. DISCLOSURE TO
UNAUTHORIZED PERSONS WOULD LIKELY CAUSE SUBSTANTIAL COMPETITIVE HARM TO
RAYTHEON COMPANY'S BUSINESS POSITION. NEITHER SAID DOCUMENT NOR ITS
CONTENTS SHALL BE FURNISHED OR DISCLOSED TO OR COPIED OR USED BY PERSONS
OUTSIDE RAYTHEON COMPANY WITHOUT THE EXPRESS WRITTEN APPROVAL OF RAYTHEON
COMPANY.
THIS PROPRIETARY NOTICE IS NOT APPLICABLE IF DELIVERED TO THE U.S.
GOVERNMENT.
UNPUBLISHED WORK - COPYRIGHT RAYTHEON COMPANY.
-------------------------------------------------------------------------*/
using System;
using System.IO;
using System.Linq;
using System.Text;
namespace Raytheon.Common
{
/// <summary>
/// A collection of utilities.
/// </summary>
public static class Util
{
#region PublicFunctions
/// <summary>
///
/// </summary>
/// <param name="registerContents"></param>
/// <param name="startBit"></param>
/// <param name="numOfBitsToMask"></param>
/// <param name="inverseFlag"></param>
/// <returns></returns>
public static uint ApplyBitMask(uint registerContents, int startBit, int numOfBitsToMask, bool inverseFlag = false)
{
uint mask = 1;
for (int i = 0; i < numOfBitsToMask - 1; i++)
{
mask = mask << 1;
mask = mask + 1;
}
//left shift to startbit position
mask = mask << startBit;
//Inverse the mask
if (inverseFlag)
{
mask = ~mask;
}
//Apply Mask and return
return (registerContents & mask);
}
/// <summary>
///
/// </summary>
/// <param name="ba"></param>
/// <returns></returns>
public static string ByteArrayToHexString(byte[] ba)
{
StringBuilder hex = new StringBuilder(ba.Length * 2);
foreach (byte b in ba)
{
hex.AppendFormat("{0:x2}", b);
}
return hex.ToString();
}
/// <summary>
///
/// </summary>
/// <param name="src"></param>
/// <param name="pattern"></param>
/// <returns></returns>
public static int ByteArraySearch(byte[] src, int srcStartIndex, byte[] pattern)
{
int maxFirstCharSlot = src.Length - pattern.Length + 1;
for (int i = srcStartIndex; i < maxFirstCharSlot; i++)
{
if (src[i] != pattern[0]) // compare only first byte
{
continue;
}
// found a match on first byte, now try to match rest of the pattern
for (int j = pattern.Length - 1; j >= 1; j--)
{
if (src[i + j] != pattern[j]) break;
if (j == 1) return i;
}
}
return -1;
}
/// <summary>
///
/// </summary>
/// <param name="stringToConvert"></param>
/// <returns></returns>
public static double ConvertStringToDouble(string stringToConvert)
{
try
{
double rsp = Convert.ToDouble(stringToConvert);
return rsp;
}
catch (Exception err)
{
throw new Exception("Util::ConvertStringToDouble() - " + err.Message + ". Faulty String: " + stringToConvert);
}
}
/// <summary>
/// Converts a string to a ushort
/// </summary>
/// <param name="stringToConvert"></param>
/// <returns></returns>
public static ushort ConvertStringToUInt16(string stringToConvert)
{
try
{
ushort rsp = Convert.ToUInt16(stringToConvert);
return rsp;
}
catch (Exception err)
{
throw new Exception("Util::ConvertStringToUInt16() - " + err.Message + ". Faulty String: " + stringToConvert);
}
}
/// <summary>
///
/// </summary>
/// <param name="stringToConvert"></param>
/// <returns></returns>
public static int ConvertStringToInt32(string stringToConvert)
{
try
{
int rsp = Convert.ToInt32(stringToConvert);
return rsp;
}
catch (Exception err)
{
throw new Exception("Util::ConvertStringToInt32() - " + err.Message + ". Faulty String: " + stringToConvert);
}
}
/// <summary>
///
/// </summary>
/// <param name="sourceDirName"></param>
/// <param name="destDirName"></param>
/// <param name="copySubDirs"></param>
public static void DirectoryCopy(string sourceDirName, string destDirName, bool copySubDirs)
{
// Get the subdirectories for the specified directory.
DirectoryInfo dir = new DirectoryInfo(sourceDirName);
if (!dir.Exists)
{
throw new DirectoryNotFoundException(
"Source directory does not exist or could not be found: "
+ sourceDirName);
}
DirectoryInfo[] dirs = dir.GetDirectories();
// If the destination directory doesn't exist, create it.
if (!Directory.Exists(destDirName))
{
Directory.CreateDirectory(destDirName);
}
// Get the files in the directory and copy them to the new location.
FileInfo[] files = dir.GetFiles();
foreach (FileInfo file in files)
{
string temppath = Path.Combine(destDirName, file.Name);
file.CopyTo(temppath, false);
}
// If copying subdirectories, copy them and their contents to new location.
if (copySubDirs)
{
foreach (DirectoryInfo subdir in dirs)
{
string temppath = Path.Combine(destDirName, subdir.Name);
DirectoryCopy(subdir.FullName, temppath, copySubDirs);
}
}
}
/// <summary>
/// Compares the contents of two files
/// </summary>
/// <param name="fileName1"></param>
/// <param name="fileName2"></param>
/// <returns></returns>
public static bool FileEquals(string fileName1, string fileName2)
{
using (var file1 = new FileStream(fileName1, FileMode.Open))
using (var file2 = new FileStream(fileName2, FileMode.Open))
return FileStreamEquals(file1, file2);
}
/// <summary>
/// Compares the contents of two file streams
/// </summary>
/// <param name="stream1"></param>
/// <param name="stream2"></param>
/// <returns></returns>
public static bool FileStreamEquals(Stream stream1, Stream stream2)
{
const int BUFFER_SIZE = 2048;
byte[] buffer1 = new byte[BUFFER_SIZE]; //buffer size
byte[] buffer2 = new byte[BUFFER_SIZE];
while (true)
{
int count1 = stream1.Read(buffer1, 0, BUFFER_SIZE);
int count2 = stream2.Read(buffer2, 0, BUFFER_SIZE);
if (count1 != count2)
{
return false;
}
if (count1 == 0)
{
return true;
}
// You might replace the following with an efficient "memcmp"
if (!buffer1.Take(count1).SequenceEqual(buffer2.Take(count2)))
{
return false;
}
}
}
/// <summary>
/// Get a timestamp in string form.
/// </summary>
/// <returns>The timestamp string.</returns>
public static string GetTimeString()
{
DateTime nowTime = DateTime.Now;
string time = nowTime.Year.ToString("0000") + "_" + nowTime.Month.ToString("00") + "_" + nowTime.Day.ToString("00") + "_" + nowTime.Hour.ToString("00") + "_" + nowTime.Minute.ToString("00") + "_" + nowTime.Second.ToString("00") + "_" + nowTime.Millisecond.ToString("000");
return time;
}
/// <summary>
///
/// </summary>
/// <param name="address"></param>
/// <param name="pingTimeOutInMs"></param>
/// <returns></returns>
public static bool IsIpAddressReachable(string address, int pingTimeOutInMs = 1000)
{
bool isReachable = false;
System.Net.NetworkInformation.Ping p = new System.Net.NetworkInformation.Ping();
System.Net.NetworkInformation.PingReply reply = p.Send(address, pingTimeOutInMs);
if (reply.Status == System.Net.NetworkInformation.IPStatus.Success)
{
isReachable = true;
}
return isReachable;
}
/// <summary>
///
/// </summary>
/// <param name="registerContents"></param>
/// <param name="startBit"></param>
/// <param name="numOfBitsToMask"></param>
/// <returns></returns>
public static uint ParseRegisterItem(uint registerContents, int startBit, int numOfBitsToMask)
{
uint mask = 1;
for (int i = 0; i < numOfBitsToMask - 1; i++)
{
mask = mask << 1;
mask = mask + 1;
}
//left shift to startbit position
mask = mask << startBit;
uint dataToReturn = (registerContents & mask);
dataToReturn = dataToReturn >> startBit;
//Apply Mask and return
return dataToReturn;
}
/// <summary>
///
/// </summary>
/// <param name="data"></param>
/// <returns></returns>
public static ushort ReverseBits16(ushort data)
{
ushort reversedData = 0;
for (int i = 0; i < 16; ++i)
{
reversedData <<= 1;
reversedData |= (ushort)(data & 1);
data >>= 1;
}
return reversedData;
}
/// <summary>
///
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
public static byte[] Swap(byte[] input)
{
Array.Reverse(input);
return input;
}
/// <summary>
///
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
public static double Swap(double input)
{
byte[] byteArray = BitConverter.GetBytes(input);
Array.Reverse(byteArray);
return BitConverter.ToDouble(byteArray, 0);
}
/// <summary>
///
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
public static ulong Swap(ulong input)
{
byte[] byteArray = BitConverter.GetBytes(input);
Array.Reverse(byteArray);
return BitConverter.ToUInt64(byteArray, 0);
}
/// <summary>
/// Reverse the byte order of the input parameter (16bit).
/// </summary>
/// <param name="input">16bit data.</param>
/// <returns>Reversed 16bit data.</returns>
public static ushort Swap(ushort input)
{
byte[] byteArray = BitConverter.GetBytes(input);
Array.Reverse(byteArray);
return BitConverter.ToUInt16(byteArray, 0);
}
/// <summary>
/// Reverse the byte order of the input parameter (32bit).
/// </summary>
/// <param name="input">32bit data.</param>
/// <returns>Reversed 32bit data.</returns>
public static uint Swap(uint input)
{
byte[] byteArray = BitConverter.GetBytes(input);
Array.Reverse(byteArray);
return BitConverter.ToUInt32(byteArray, 0);
}
/// <summary>
///
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
public static float Swap(float input)
{
byte[] byteArray = BitConverter.GetBytes(input);
Array.Reverse(byteArray);
return BitConverter.ToSingle(byteArray, 0);
}
/// <summary>
///
/// </summary>
/// <param name="dataBeingSwapped"></param>
/// <returns></returns>
public static uint SwapHighAndLowBytes(uint dataBeingSwapped)
{
//Using a 16-bit shift to move around four hex values at a time
dataBeingSwapped = ((dataBeingSwapped & 0xFFFF) << 16) | ((uint)(dataBeingSwapped & 0xFFFF0000) >> 16);
return dataBeingSwapped;
}
#endregion
}
}

View File

@@ -0,0 +1,248 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
namespace Win_API
{
public static class NativeMethods
{
// The following GitHub link was very helpful in understanding how some of the WinApi calls work together, as well as
// for certain const values like DIGCF_PRESENT. https://github.com/mikeobrien/HidLibrary/tree/dc9026067dd0c511574c8ce726682ece4f45939e
//https://docs.microsoft.com/en-us/windows-hardware/drivers/install/setupapi
//https://docs.microsoft.com/en-us/windows-hardware/drivers/hid/introduction-to-hid-concepts
public const uint GENERIC_READ = 0x80000000;
public const uint GENERIC_WRITE = 0x40000000;
public const int FILE_FLAG_OVERLAPPED = 0x40000000;
public const int FILE_ATTRIBUTE_NORMAL = 0x128;
public const short DIGCF_PRESENT = 0x2;
public const short DIGCF_DEVICEINTERFACE = 0x10;
public const int DIGCF_ALLCLASSES = 0x4;
public static readonly IntPtr INVALID_HANDLE_VALUE = new IntPtr(-1);
/// <summary>
/// Zero prevents other processes from opening a file or device if they request delete, read, or write access.
/// </summary>
public enum FileShareMode
{
Zero = 0x00000000,
FILE_SHARE_DELETE = 0x00000004,
FILE_SHARE_READ = 0x00000001,
FILE_SHARE_WRITE = 0x00000002
}
public struct SECURITY_ATTRIBUTES
{
public int nLength;
public IntPtr lpSecurityDescriptor;
public bool bInheritHandle;
}
[DllImport("kernel32.dll")]
public static extern bool CancelIo(IntPtr hFile);
[DllImport("kernel32.dll")]
public static extern IntPtr CreateFileA(
string lpFileName,
uint dwDesiredAccess,
int dwShareMode,
ref SECURITY_ATTRIBUTES lpSecurityAttributes,
int dwCreationDisposition,
int dwFlagsAndAttributes,
IntPtr hTemplateFile);
[DllImport("kernel32.dll")]
public static extern bool ReadFile(
IntPtr hFile,
IntPtr lpBuffer,
uint nNumberOfBytesToRead,
out uint lpNumberOfBytesRead,
[In] ref System.Threading.NativeOverlapped lpOverlapped);
[DllImport("kernel32.dll")]
public static extern bool WriteFile(
IntPtr hFile,
byte[] lpBuffer,
uint nNumberOfBytesToWrite,
out uint lpNumberOfBytesWritten,
[In] ref System.Threading.NativeOverlapped lpOverlapped);
[DllImport("kernel32.dll")]
public static extern bool CloseHandle(IntPtr hHandle);
/// <summary>
/// The caller of this function must delete the returned device information set when it is no longer needed by calling SetupDiDestroyDeviceInfoList.
/// </summary>
/// <param name="guid"></param>
/// <param name="hwndParent"></param>
/// <returns></returns>
[DllImport("Setupapi.dll")]
public static extern IntPtr SetupDiCreateDeviceInfoList(Guid Guid, IntPtr HwndParent);
[DllImport("setupapi.dll")]
public static extern bool SetupDiCreateDeviceInfo(IntPtr DeviceInfoSet, string DeviceName, Guid ClassGuid, string DeviceDescription, uint CreationFlags, IntPtr DeviceInfoData);
[DllImport("setupapi.dll")]
public static extern bool SetupDiEnumDeviceInfo(IntPtr DeviceInfoSet, uint MemberIndex, ref SP_DEVINFO_DATA DeviceInfoData);
[DllImport("setupapi.dll")]
public static extern bool SetupDiEnumDeviceInterfaces(IntPtr DeviceInfoSet, ref SP_DEVINFO_DATA DeviceInfoData, Guid InterfaceClassGuid, uint MemberIndex, ref SP_DEVICE_INTERFACE_DATA DeviceInterfaceData);
[DllImport("setupapi.dll")]
public static extern bool SetupDiGetDeviceInterfaceDetail(IntPtr DeviceInfoSet, ref SP_DEVICE_INTERFACE_DATA DeviceInterfaceData, IntPtr DeviceInterfaceDetailData, uint DeviceInterfaceDetailDataSize, ref uint RequiredSize, IntPtr DeviceInfoData);
[DllImport("setupapi.dll")]
public static extern bool SetupDiGetDeviceInterfaceDetail(IntPtr DeviceInfoSet, ref SP_DEVICE_INTERFACE_DATA DeviceInterfaceData, ref SP_DEVICE_INTERFACE_DETAIL_DATA DeviceInterfaceDetailData, uint DeviceInterfaceDetailDataSize, ref uint RequiredSize, IntPtr DeviceInfoData);
[DllImport("setupapi.dll")]
public static extern bool SetupDiGetClassDevs(Guid ClassGuid, IntPtr Enumerator, IntPtr hwndParent, uint Flags);
[DllImport("setupapi.dll")]
public static extern bool SetupDiDestroyDeviceInfoList(IntPtr DeviceInfoSet);
/// <summary>
/// HidD_GetAttributes returns TRUE if succeeds; otherwise, it returns FALSE.
/// </summary>
/// <param name="HidDeviceObject"></param>
/// <param name="Attributes"></param>
/// <returns></returns>
[DllImport("hid.dll")]
public static extern bool HidD_GetAttributes(IntPtr HidDeviceObject, HIDD_ATTRIBUTES Attributes);
/// <summary>
/// [out] Pointer to a caller-allocated GUID buffer that the routine uses to return the device interface GUID for HIDClass devices.
/// </summary>
/// <param name="HidGuid"></param>
[DllImport("hid.dll")]
public static extern void HidD_GetHidGuid(out Guid HidGuid);
[DllImport("hid.dll")]
public static extern bool HidD_GetIndexString(IntPtr HidDeviceObject, ulong StringIndex, out string Buffer, ulong BufferLength);
/// <summary>
/// The maximum possible number of characters in an embedded string is device specific. For USB devices, the maximum string length is 126 wide characters (not including the terminating NULL character).
/// If the supplied buffer is not <= 4093 bytes(2^12 3) the call may fail(depending on the underlying protocol, HID/Bluetooth/SPI) with error code ERROR_GEN_FAILURE(0x0000001f).
/// </summary>
/// <param name="HidDeviceObject"></param>
/// <param name="Buffer"></param>
/// <param name="BufferLength"></param>
/// <returns>bool</returns>
[DllImport("hid.dll")]
public static extern bool HidD_GetManufacturerString(IntPtr HidDeviceObject, out string Buffer, ulong BufferLength);
/// <summary>
/// HidD_GetPhysicalDescriptor returns TRUE if it succeeds; otherwise, it returns FALSE. Use GetLastError to get extended error information.
/// </summary>
/// <param name="HidDeviceObject"></param>
/// <param name="Buffer"></param>
/// <param name="BufferLength"></param>
/// <returns></returns>
[DllImport("hid.dll")]
public static extern bool HidD_GetPhysicalDescriptor(IntPtr HidDeviceObject, out string Buffer, [In] ulong BufferLength);
[DllImport("hid.dll")]
public static extern bool HidD_GetPreparsedData(IntPtr HidDeviceObject, out HID_COLLECTION_INFORMATION PreparsedData);
/// <summary>
/// The supplied buffer must be <= 4093 bytes (2^12 3).
/// </summary>
/// <param name="HidDeviceObject"></param>
/// <param name="Buffer"></param>
/// <param name="BufferLength"></param>
/// <returns></returns>
[DllImport("hid.dll")]
public static extern bool HidD_GetProductString(IntPtr HidDeviceObject, out string Buffer, ulong BufferLength);
[DllImport("hid.dll")]
public static extern bool HidD_GetSerialNumberString(IntPtr HidDeviceObject, out string Buffer, ulong BufferLength);
[DllImport("hid.dll")]
public static extern bool HidD_GetNumInputBuffers(IntPtr HidDeviceObject, out ulong NumberBuffers);
[DllImport("hid.dll")]
public static extern bool HidD_SetNumInputBuffers(IntPtr HidDeviceObject, ulong NumberBuffers);
/// <summary>
/// A caller of HidD_GetAttributes, uses this structure to obtain a device's vendor information.
/// Before using a HIDD_ATTRIBUTES structure with HIDClass support routines, the caller must set the Size member.
/// </summary>
public struct HIDD_ATTRIBUTES
{
public ulong Size;
public ushort VendorID;
public ushort ProductID;
public ushort VersionNumber;
}
public struct HID_COLLECTION_INFORMATION
{
public ulong DescriptorSize;
public bool Polled;
public char[] Reserved1;
public ushort VendorID;
public ushort ProductID;
public ushort VersionNumber;
}
[StructLayout(LayoutKind.Sequential)]
public struct SP_DEVICE_INTERFACE_DATA
{
public uint cbSize;
public Guid InterfaceClassGuid;
public uint Flags;
public IntPtr Reserved;
}
[StructLayout(LayoutKind.Sequential)]
public struct SP_DEVINFO_DATA
{
public uint cbSize;
public Guid ClassGuid;
public uint DevInst;
public IntPtr Reserved;
}
[StructLayout(LayoutKind.Sequential)]
public struct SP_DEVICE_INTERFACE_DETAIL_DATA
{
public uint cbSize;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
public string DevicePath;
}
public static SECURITY_ATTRIBUTES InitWithDefaultAttributes()
{
SECURITY_ATTRIBUTES attributes = new SECURITY_ATTRIBUTES
{
bInheritHandle = false,
lpSecurityDescriptor = IntPtr.Zero
};
attributes.nLength = Marshal.SizeOf(attributes);
return attributes;
}
public static IntPtr CreateNonManagedBuffer(byte[] buffer)
{
return Marshal.AllocHGlobal(buffer.Length);
}
public static byte[] CopyUnManagedBufferToManagedBuffer(IntPtr unManagedBuffer, int bytesRead)
{
var buffer = new byte[] { };
Marshal.Copy(unManagedBuffer, buffer, 0, bytesRead);
return buffer;
}
public static void DisposeNonManagedObject(IntPtr nonManagedObj)
{
Marshal.FreeHGlobal(nonManagedObj);
}
}
}

View File

@@ -0,0 +1,49 @@
// **********************************************************************************************************
// ActiveHealthMonitorData.cs
// 2/17/2023
// NGI - Next Generation Interceptor
//
// Contract No. HQ0856-21-C-0003/1022000209
//
// THIS DOCUMENT DOES NOT CONTAIN TECHNOLOGY OR TECHNICAL DATA CONTROLLED UNDER EITHER THE U.S.
// INTERNATIONAL TRAFFIC IN ARMS REGULATIONS OR THE U.S. EXPORT ADMINISTRATION REGULATIONS.
//
// RAYTHEON PROPRIETARY: THIS DOCUMENT CONTAINS DATA OR INFORMATION PROPRIETARY TO RAYTHEON
// COMPANY AND IS RESTRICTED TO USE ONLY BY PERSONS AUTHORIZED BY RAYTHEON COMPANY IN WRITING TO USE IT.
// DISCLOSURE TO UNAUTHORIZED PERSONS WOULD LIKELY CAUSE SUBSTANTIAL COMPETITIVE HARM TO RAYTHEON
// COMPANY'S BUSINESS POSITION. NEITHER SAID DOCUMENT NOR ITS CONTENTS SHALL BE FURNISHED OR DISCLOSED
// TO OR COPIED OR USED BY PERSONS OUTSIDE RAYTHEON COMPANY WITHOUT THE EXPRESS WRITTEN APPROVAL OF
// RAYTHEON COMPANY.
//
// UNPUBLISHED WORK - COPYRIGHT RAYTHEON COMPANY.
//
// DESTRUCTION NOTICE: FOR CLASSIFIED DOCUMENTS FOLLOW THE PROCEDURES IN DOD 5220.22-M,
// NATIONAL INDUSTRIAL SECURITY PROGRAM OPERATING MANUAL, FEBRUARY 2006,
// INCORPORATING CHANGE 1, MARCH 28, 2013, CHAPTER 5, SECTION 7, OR DODM 5200.01-VOLUME 3,
// DOD INFORMATION SECURITY PROGRAM: PROTECTION OF CLASSIFIED INFORMATION, ENCLOSURE 3,
// SECTION 17. FOR CONTROLLED UNCLASSIFIED INFORMATION FOLLOW THE PROCEDURES IN DODM 5200.01-VOLUME 4,
// INFORMATION SECURITY PROGRAM: CONTROLLED UNCLASSIFIED INFORMATION.
//
// CONTROLLED BY: MISSILE DEFENSE AGENCY
// CONTROLLED BY: GROUND-BASED MIDCOURSE DEFENSE PROGRAM OFFICE
// CUI CATEGORY: CTI
// DISTRIBUTION/DISSEMINATION CONTROL: F
// POC: Alex Kravchenko (1118268)
// **********************************************************************************************************
namespace Raytheon.Common
{
public enum MonitorStatus
{
NOMINAL,
WARNING,
ABORT
}
public struct ActiveHealthMonitorData
{
public string itemName;
public double dataValue;
public MonitorStatus status;
}
}

View File

@@ -0,0 +1,55 @@
// **********************************************************************************************************
// PowerMonitorCallbackData.cs
// 2/17/2023
// NGI - Next Generation Interceptor
//
// Contract No. HQ0856-21-C-0003/1022000209
//
// THIS DOCUMENT DOES NOT CONTAIN TECHNOLOGY OR TECHNICAL DATA CONTROLLED UNDER EITHER THE U.S.
// INTERNATIONAL TRAFFIC IN ARMS REGULATIONS OR THE U.S. EXPORT ADMINISTRATION REGULATIONS.
//
// RAYTHEON PROPRIETARY: THIS DOCUMENT CONTAINS DATA OR INFORMATION PROPRIETARY TO RAYTHEON
// COMPANY AND IS RESTRICTED TO USE ONLY BY PERSONS AUTHORIZED BY RAYTHEON COMPANY IN WRITING TO USE IT.
// DISCLOSURE TO UNAUTHORIZED PERSONS WOULD LIKELY CAUSE SUBSTANTIAL COMPETITIVE HARM TO RAYTHEON
// COMPANY'S BUSINESS POSITION. NEITHER SAID DOCUMENT NOR ITS CONTENTS SHALL BE FURNISHED OR DISCLOSED
// TO OR COPIED OR USED BY PERSONS OUTSIDE RAYTHEON COMPANY WITHOUT THE EXPRESS WRITTEN APPROVAL OF
// RAYTHEON COMPANY.
//
// UNPUBLISHED WORK - COPYRIGHT RAYTHEON COMPANY.
//
// DESTRUCTION NOTICE: FOR CLASSIFIED DOCUMENTS FOLLOW THE PROCEDURES IN DOD 5220.22-M,
// NATIONAL INDUSTRIAL SECURITY PROGRAM OPERATING MANUAL, FEBRUARY 2006,
// INCORPORATING CHANGE 1, MARCH 28, 2013, CHAPTER 5, SECTION 7, OR DODM 5200.01-VOLUME 3,
// DOD INFORMATION SECURITY PROGRAM: PROTECTION OF CLASSIFIED INFORMATION, ENCLOSURE 3,
// SECTION 17. FOR CONTROLLED UNCLASSIFIED INFORMATION FOLLOW THE PROCEDURES IN DODM 5200.01-VOLUME 4,
// INFORMATION SECURITY PROGRAM: CONTROLLED UNCLASSIFIED INFORMATION.
//
// CONTROLLED BY: MISSILE DEFENSE AGENCY
// CONTROLLED BY: GROUND-BASED MIDCOURSE DEFENSE PROGRAM OFFICE
// CUI CATEGORY: CTI
// DISTRIBUTION/DISSEMINATION CONTROL: F
// POC: Alex Kravchenko (1118268)
// **********************************************************************************************************
namespace Raytheon.Common
{
public struct PowerMonitorCallbackData
{
public string powerModule;
public double overVoltageProtectionValue;
public double overCurrentProtectionValue;
public double voltage;
public double voltageSetpoint;
public double current;
public bool outputStatus;
public int ovpocpStatus;
}
}

View File

@@ -0,0 +1,61 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="$(SolutionDir)Solution.props" />
<PropertyGroup>
<TargetFramework>net472</TargetFramework>
<LangVersion>9.0</LangVersion>
<OutputType>Library</OutputType>
<AssemblyName>Raytheon.Common</AssemblyName>
<Product>Raytheon Common Library</Product>
<Description>Raytheon Common Library</Description>
<!-- Static versioning (Suitable for Development) -->
<!-- Disable the line below for dynamic versioning -->
<Version>1.0.0</Version>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<PropertyGroup>
<NoWarn>CS0649</NoWarn>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="NLog" Version="5.0.0" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.2" />
</ItemGroup>
<ItemGroup>
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.ComponentModel.Composition" />
</ItemGroup>
<ItemGroup>
<COMReference Include="Microsoft.Office.Core">
<Guid>{2DF8D04C-5BFA-101B-BDE5-00AA0044DE52}</Guid>
<VersionMajor>2</VersionMajor>
<VersionMinor>8</VersionMinor>
<Lcid>0</Lcid>
<WrapperTool>primary</WrapperTool>
<Isolated>False</Isolated>
<EmbedInteropTypes>True</EmbedInteropTypes>
</COMReference>
<COMReference Include="Microsoft.Office.Interop.Excel">
<Guid>{00020813-0000-0000-C000-000000000046}</Guid>
<VersionMajor>1</VersionMajor>
<VersionMinor>9</VersionMinor>
<Lcid>0</Lcid>
<WrapperTool>primary</WrapperTool>
<Isolated>False</Isolated>
<EmbedInteropTypes>True</EmbedInteropTypes>
</COMReference>
<COMReference Include="VBIDE">
<Guid>{0002E157-0000-0000-C000-000000000046}</Guid>
<VersionMajor>5</VersionMajor>
<VersionMinor>3</VersionMinor>
<Lcid>0</Lcid>
<WrapperTool>primary</WrapperTool>
<Isolated>False</Isolated>
<EmbedInteropTypes>True</EmbedInteropTypes>
</COMReference>
</ItemGroup>
</Project>

View File

@@ -0,0 +1,247 @@
// UNCLASSIFIED
/*-------------------------------------------------------------------------
RAYTHEON PROPRIETARY: THIS DOCUMENT CONTAINS DATA OR INFORMATION
PROPRIETARY TO RAYTHEON COMPANY AND IS RESTRICTED TO USE ONLY BY PERSONS
AUTHORIZED BY RAYTHEON COMPANY IN WRITING TO USE IT. DISCLOSURE TO
UNAUTHORIZED PERSONS WOULD LIKELY CAUSE SUBSTANTIAL COMPETITIVE HARM TO
RAYTHEON COMPANY'S BUSINESS POSITION. NEITHER SAID DOCUMENT NOR ITS
CONTENTS SHALL BE FURNISHED OR DISCLOSED TO OR COPIED OR USED BY PERSONS
OUTSIDE RAYTHEON COMPANY WITHOUT THE EXPRESS WRITTEN APPROVAL OF RAYTHEON
COMPANY.
THIS PROPRIETARY NOTICE IS NOT APPLICABLE IF DELIVERED TO THE U.S.
GOVERNMENT.
UNPUBLISHED WORK - COPYRIGHT RAYTHEON COMPANY.
-------------------------------------------------------------------------*/
using System;
using System.Threading;
namespace Raytheon.Common
{
/// <summary>
/// Processes messages from a buffer
/// </summary>
public class MsgProcessorWorker : IWorkerInterface
{
#region PrivateClassMembers
private IMsgParser _msgParser;
private DataBuffer _dataBuffer;
private AutoResetEvent _dataInBufferEvent;
private AutoResetEvent _quitEvent;
private bool _threadQuitControl;
private MsgDevice.CompleteMessageCallback _completeMsgCallback;
#endregion
#region PrivateFunctions
/// <summary>
/// Dispose of this objects resources
/// </summary>
/// <param name="disposing"></param>
protected virtual void Dispose(bool disposing)
{
try
{
if (disposing)
{
_quitEvent.Dispose();
}
}
catch (Exception err)
{
try
{
ErrorLogger.Instance().Write(err.Message + "\r\n" + err.StackTrace);
}
catch (Exception)
{
//Do not rethrow. Exception from error logger that has already been garbage collected
}
}
}
#endregion
#region PublicFuctions
/// <summary>
/// Constructor
/// </summary>
/// <param name="msgParser">Parses out the messages</param>
/// <param name="dataBuffer">The buffer to parse from</param>
/// <param name="dataInBufferEvent">A singal to let us know that data has arrived</param>
public MsgProcessorWorker(IMsgParser msgParser, ref DataBuffer dataBuffer, ref AutoResetEvent dataInBufferEvent)
{
_msgParser = msgParser;
_dataBuffer = dataBuffer;
_dataInBufferEvent = dataInBufferEvent;
_threadQuitControl = false;
_quitEvent = new AutoResetEvent(false);
}
/// <summary>
/// The finalizer for cleaing up resources
/// </summary>
~MsgProcessorWorker()
{
Dispose(false);
}
/// <summary>
/// Dispose of this objects resources
/// </summary>
public void Dispose()
{
try
{
Dispose(true);
GC.SuppressFinalize(this);
}
catch (Exception err)
{
try
{
ErrorLogger.Instance().Write(err.Message + "\r\n" + err.StackTrace);
}
catch (Exception)
{
//Do not rethrow. Exception from error logger that has already been garbage collected
}
}
}
/// <summary>
/// Parses out messages from the data buffer and then issues callback to the handler with the completed message
/// </summary>
unsafe public void DoWork()
{
try
{
if (_completeMsgCallback == null)
{
throw new Exception("MsgProcessorWorker::DoWork() - Callback not set");
}
WaitHandle[] waithandles = new WaitHandle[2];
waithandles[0] = _dataInBufferEvent;
waithandles[1] = _quitEvent;
bool isTheWorkDone = false;
uint numBytesProcessedInLastIteration = 0;
while (isTheWorkDone == false)
{
int eventIndex = 0;
eventIndex = WaitHandle.WaitAny(waithandles, 100);
_dataInBufferEvent.Reset();
uint dataBufferBytesUsed = _dataBuffer.BytesUsed;
if (eventIndex == 0 || dataBufferBytesUsed > 0) // _dataInBufferEvent
{
uint numBytesToProcess = 0;
IntPtr pStartOfData = _dataBuffer.CheckOutStartOfData(ref numBytesToProcess);
bool isThisRoundOfProcessingDone = false;
uint ourCopyOfDataIndex = 0;
numBytesProcessedInLastIteration = 0;
while (isThisRoundOfProcessingDone == false)
{
uint numBytesLeftInTempBuffer = numBytesToProcess - ourCopyOfDataIndex;
if (numBytesLeftInTempBuffer == 0)
{
isThisRoundOfProcessingDone = true;
}
else
{
uint numBytesToRemove = 0;
uint msgId = 0;
uint errorCode = 0;
IntPtr payLoadPtr = IntPtr.Add(pStartOfData, (int)ourCopyOfDataIndex);
if (_msgParser.Run(payLoadPtr, numBytesLeftInTempBuffer, ref numBytesToRemove, ref msgId, ref errorCode) == true)
{
string msg = "MsgProcessorWorker::DoWork() - removing " + numBytesToRemove.ToString() + " bytes, for msg id: " + msgId.ToString("X8");
ErrorLogger.Instance().Write(msg, ErrorLogger.LogLevel.INFO);
// we have a complete message, invoke the call back
_completeMsgCallback(msgId, payLoadPtr, numBytesToRemove, errorCode);
}
if (numBytesToRemove == 0)
{
isThisRoundOfProcessingDone = true;
}
else
{
ourCopyOfDataIndex += numBytesToRemove;
_dataBuffer.Remove(numBytesToRemove);
numBytesProcessedInLastIteration += ourCopyOfDataIndex;
}
// were we signaled to quit?
if (_threadQuitControl == true)
{
ErrorLogger.Instance().Write("MsgProcessorWorker::DoWork() - in the midst of procesing data, the quit event was detected, exiting", ErrorLogger.LogLevel.INFO);
isTheWorkDone = true;
}
}
}
//Check start of data back in since we are done with it
_dataBuffer.CheckInStartOfData();
}
else if (eventIndex == 1) // _quitEvent
{
ErrorLogger.Instance().Write("MsgProcessorWorker::DoWork() - quit event was detected, exiting", ErrorLogger.LogLevel.INFO);
isTheWorkDone = true;
}
else if (eventIndex == WaitHandle.WaitTimeout)
{
// expected, continue
}
else
{
ErrorLogger.Instance().Write("MsgProcessorWorker::DoWork() - Unhandled return from WaitHandle.WaitAny(): " + eventIndex.ToString());
}
}
ErrorLogger.Instance().Write("MsgProcessorWorker::DoWork() - exiting", ErrorLogger.LogLevel.INFO);
}
catch (Exception err)
{
ErrorLogger.Instance().Write(err.Message + "\r\n" + err.StackTrace);
}
}
/// <summary>
/// Sets the call back function
/// </summary>
/// <param name="callback">The call back function</param>
public void SetCallback(MsgDevice.CompleteMessageCallback callback)
{
_completeMsgCallback = callback;
}
/// <summary>
/// Command the worker to stop
/// </summary>
public void QuitWork()
{
_threadQuitControl = true;
_quitEvent.Set();
}
#endregion
}
}

View File

@@ -0,0 +1,382 @@
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Runtime.Serialization;
namespace Raytheon.Units
{
/// <summary>
/// This class represents an acceleration.
///
/// It has no constructors. Instead, it provides multiple methods for creating objects of this
/// type. Those methods are of the form FromXXX, where XXX is a unit (e.g.
/// FromMetersPerSecSqrd).
///
/// Properties (e.g. FeetPerSecSqrd) are provided to convert the value to other units and return
/// as type double.
///
/// Methods (operator overloads) are provided to perform calculations with related types (e.g.
/// Velocity, Length).
/// </summary>
[Serializable]
[DataContract]
public class Acceleration
{
public enum Unit
{
FeetPerSecSqrd,
MetersPerSecSqrd,
Gs
}
public static IDictionary<Unit, List<string>> UnitAbbreviations = new Dictionary<Unit, List<string>>()
{
{Unit.FeetPerSecSqrd, new List<string>(){ "ft/sec^2" } },
{Unit.MetersPerSecSqrd, new List<string>(){ "m/sec^2" } },
{Unit.Gs, new List<string>(){ "g" } }
};
private const Unit DefaultUnits = Unit.MetersPerSecSqrd;
private const double FeetPerMeter = 3.280839895013123;
private const double Gravity = 9.80665; // m/sec^2
[DataMember(Name = "Acceleration", IsRequired = true)]
private double _acceleration; // meters/seconds^2
// map: unit => abbreviation, conversion method and property
private static IDictionary<Unit, UnitInfo<Acceleration>> _unitInfo = new Dictionary<Unit, UnitInfo<Acceleration>>()
{
{ Unit.FeetPerSecSqrd, new UnitInfo<Acceleration>(UnitAbbreviations[Unit.FeetPerSecSqrd], FromFeetPerSecSqrd, typeof(Acceleration).GetProperty("FeetPerSecSqrd").GetGetMethod()) },
{ Unit.MetersPerSecSqrd, new UnitInfo<Acceleration>(UnitAbbreviations[Unit.MetersPerSecSqrd], FromMetersPerSecSqrd, typeof(Acceleration).GetProperty("MetersPerSecSqrd").GetGetMethod()) },
{ Unit.Gs, new UnitInfo<Acceleration>(UnitAbbreviations[Unit.Gs], FromGs, typeof(Acceleration).GetProperty("Gs").GetGetMethod()) }
};
/// <summary>
/// Prevents a default instance of the <see cref="Acceleration"/> class from being created.
/// Use FromXXX methods to create objects of this type.
/// </summary>
/// <exception cref="System.Exception">No one should be calling this, it is only here to prevent users from creating default object</exception>
private Acceleration()
{
throw new InvalidOperationException("No one should be calling this, it is only here to prevent users from creating default object");
}
/// <summary>
/// ctor used by this class to create objects in FromXXX methods
/// </summary>
/// <param name="acceleration">The acceleration - m/sec^2.</param>
private Acceleration(double acceleration)
{
_acceleration = acceleration;
}
#region conversion properties
/// <summary>
/// Returns feet/sec^2 as type double
/// </summary>
/// <value>
/// feet/sec^2
/// </value>
public double FeetPerSecSqrd
{
get { return _acceleration * FeetPerMeter; }
}
/// <summary>
/// returns Gs as type double
/// </summary>
public double Gs
{
get { return _acceleration / Gravity; }
}
/// <summary>
/// Returns m/sec^2 as type double
/// </summary>
/// <value>
/// m/sec^2
/// </value>
public double MetersPerSecSqrd
{
get { return _acceleration; }
}
#endregion
#region creation methods
/// <summary>
/// Returns Acceleration object interpreting passed value as ft/sec^2
/// </summary>
/// <param name="feetPerSecSqrd">ft/sec^2</param>
/// <returns></returns>
public static Acceleration FromFeetPerSecSqrd(double feetPerSecSqrd)
{
return new Acceleration(feetPerSecSqrd / FeetPerMeter);
}
/// <summary>
/// Returns Acceleration object interpreting passed value as m/sec^2
/// </summary>
/// <param name="metersPerSecSqrd">m/sec^2</param>
/// <returns></returns>
public static Acceleration FromMetersPerSecSqrd(double metersPerSecSqrd)
{
return new Acceleration(metersPerSecSqrd);
}
/// <summary>
/// Returns Acceleration object interpreting passed value as m/sec^2
/// </summary>
/// <param name="metersPerSecSqrd">m/sec^2</param>
/// <returns></returns>
public static Acceleration FromGs(double g)
{
return FromMetersPerSecSqrd(g * Gravity);
}
#endregion
#region parsing
public static Acceleration Parse(string s)
{
return Common.Parse(s, _unitInfo);
}
public static bool TryParse(string s, out Acceleration value)
{
try
{
value = Acceleration.Parse(s);
return true;
}
catch (Exception)
{
value = null;
return false;
}
}
#endregion
public override bool Equals(object obj)
{
Acceleration c = obj as Acceleration;
return (c == null) ? false : (this._acceleration == c._acceleration);
}
public override int GetHashCode()
{
return _acceleration.GetHashCode();
}
#region binary operators
// not implementing %, &, |, ^, <<, >>
public static Acceleration operator +(Acceleration left, Acceleration right)
{
if (null == left)
throw new ArgumentNullException("left", "Cannot add a null Acceleration");
if (null == right)
throw new ArgumentNullException("right", "Cannot add null Acceleration");
return new Acceleration(left._acceleration + right._acceleration);
}
public static Acceleration operator -(Acceleration left, Acceleration right)
{
if (null == left)
throw new ArgumentNullException("left", "Cannot subtract a null Acceleration");
if (null == right)
throw new ArgumentNullException("right", "Cannot subtract a null Acceleration");
return new Acceleration(left._acceleration - right._acceleration);
}
public static Acceleration operator *(Acceleration acceleration, double scalar)
{
if (null == acceleration)
throw new ArgumentNullException("acceleration", "Cannot multiply a null Acceleration");
return new Acceleration(acceleration._acceleration * scalar);
}
public static Acceleration operator *(double scalar, Acceleration acceleration)
{
if (null == acceleration)
throw new ArgumentNullException("acceleration", "Cannot multiply a null Acceleration");
return new Acceleration(scalar * acceleration._acceleration);
}
public static Acceleration operator /(Acceleration acceleration, double scalar)
{
if (null == acceleration)
throw new ArgumentNullException("acceleration", "Cannot divide a null Acceleration");
if (0.0 == scalar)
throw new DivideByZeroException("Cannot divide Acceleration by 0");
return new Acceleration(acceleration._acceleration / scalar);
}
#endregion
#region comparison operators
public static bool operator ==(Acceleration left, Acceleration right)
{
bool bReturn = false;
if (object.ReferenceEquals(left, null))
{
if (object.ReferenceEquals(right, null))
{
//both are null, so we are ==
bReturn = true;
}
}
else
{
if (!object.ReferenceEquals(left, null) &&
!object.ReferenceEquals(right, null))
{
bReturn = left._acceleration == right._acceleration;
}
}
return bReturn;
}
public static bool operator !=(Acceleration left, Acceleration right)
{
return !(left == right);
}
public static bool operator <(Acceleration left, Acceleration right)
{
if (null == left)
throw new ArgumentNullException("left", "Cannot compare null Acceleration");
if (null == right)
throw new ArgumentNullException("right", "Cannot compare null Acceleration");
return left._acceleration < right._acceleration;
}
public static bool operator >(Acceleration left, Acceleration right)
{
if (null == left)
throw new ArgumentNullException("left", "Cannot compare null Acceleration");
if (null == right)
throw new ArgumentNullException("right", "Cannot compare null Acceleration");
return left._acceleration > right._acceleration;
}
public static bool operator <=(Acceleration left, Acceleration right)
{
if (null == left)
throw new ArgumentNullException("left", "Cannot compare null Acceleration");
if (null == right)
throw new ArgumentNullException("right", "Cannot compare null Acceleration");
return left._acceleration <= right._acceleration;
}
public static bool operator >=(Acceleration left, Acceleration right)
{
if (null == left)
throw new ArgumentNullException("left", "Cannot compare null Acceleration");
if (null == right)
throw new ArgumentNullException("right", "Cannot compare null Acceleration");
return left._acceleration >= right._acceleration;
}
#endregion
#region operators with other classes
/// <summary>
/// Implements the operator * for Velocity = Acceleration * Time
/// </summary>
/// <param name="acceleration">The acceleration.</param>
/// <param name="time">The time.</param>
/// <returns>
/// Velocity
/// </returns>
public static Velocity operator *(Acceleration acceleration, PrecisionTimeSpan time)
{
if (null == acceleration)
throw new ArgumentNullException("acceleration", "Cannot multiply with null Acceleration");
if (null == time)
throw new ArgumentNullException("time", "Cannot multiply with null PrecisionTimeSpan");
return Velocity.FromMetersPerSec(acceleration.MetersPerSecSqrd * time.Seconds);
}
/// <summary>
/// Implements the operator * for Velocity = Time * Acceleration
/// </summary>
/// <param name="acceleration">The acceleration.</param>
/// <param name="time">The time.</param>
/// <returns>
/// Velocity
/// </returns>
public static Velocity operator *(PrecisionTimeSpan time, Acceleration acceleration)
{
if (null == acceleration)
throw new ArgumentNullException("acceleration", "Cannot multiply with null Acceleration");
if (null == time)
throw new ArgumentNullException("time", "Cannot multiply with null PrecisionTimeSpan");
return Velocity.FromMetersPerSec(acceleration.MetersPerSecSqrd * time.Seconds);
}
#endregion
/// <summary>
/// Returns a string appended with default units (e.g. "1.23 m/sec^2").
/// </summary>
/// <returns>
/// A string that represents this instance
/// </returns>
public override string ToString()
{
return ToString(DefaultUnits);
}
/// <summary>
/// overload that returns a string appended with specified units (e.g. "1.23 ft/sec^2").
/// </summary>
/// <param name="units"></param>
/// <returns></returns>
public string ToString(Unit units)
{
double value = (double)_unitInfo[units].PropertyGetter.Invoke(this, null);
return $"{value} {_unitInfo[units].Abbreviation[0]}";
}
}
}

View File

@@ -0,0 +1,392 @@
using System;
using System.Runtime.Serialization;
using System.Diagnostics.CodeAnalysis;
using System.Collections.Generic;
namespace Raytheon.Units
{
/// <summary>
/// This class represents an angle.
///
/// It has no constructors. Instead, it provides multiple methods for creating objects of this
/// type. Those methods are of the form FromXXX, where XXX is a unit (e.g.
/// FromDegrees).
///
/// Properties (e.g. Radians) are provided to convert the value to other units and return
/// as type double.
/// </summary>
[Serializable]
[DataContract]
public class Angle
{
public enum Unit
{
Degrees,
Radians,
Milliradians
}
public static IDictionary<Unit, List<string>> UnitAbbreviations = new Dictionary<Unit, List<string>>()
{
{Unit.Degrees, new List<string>(){ "deg" } },
{Unit.Radians, new List<string>(){ "rad" } },
{Unit.Milliradians, new List<string>(){ "mrad" } }
};
private const Unit DefaultUnits = Unit.Degrees;
private const double DegreesPerRadian = 180 / Math.PI;
private const int MilliradiansPerRadian = 1000;
[DataMember(Name = "Angle", IsRequired = true)]
private double _angle; // radians
private static IDictionary<Unit, UnitInfo<Angle>> _unitInfo = new Dictionary<Unit, UnitInfo<Angle>>()
{
{ Unit.Degrees, new UnitInfo<Angle>(UnitAbbreviations[Unit.Degrees], FromDegrees, typeof(Angle).GetProperty("Degrees").GetGetMethod()) },
{ Unit.Radians, new UnitInfo<Angle>(UnitAbbreviations[Unit.Radians], FromRadians, typeof(Angle).GetProperty("Radians").GetGetMethod()) },
{ Unit.Milliradians, new UnitInfo<Angle>(UnitAbbreviations[Unit.Milliradians], FromMilliradians, typeof(Angle).GetProperty("Milliradians").GetGetMethod()) }
};
/// <summary>
/// Prevents a default instance of the <see cref="Angle"/> class from being created.
/// Use FromXXX methods to create objects of this type.
/// </summary>
/// <exception cref="System.Exception">No one should be calling this, it is only here to prevent users from creating default object</exception>
private Angle()
{
throw new InvalidOperationException("No one should be calling this, it is only here to prevent users from creating default object");
}
/// <summary>
/// ctor used by this class to create objects in FromXXX methods
/// </summary>
/// <param name="angle">The angle - radians.</param>
private Angle(double angle)
{
_angle = angle;
}
#region conversion properties
/// <summary>
/// Returns degrees as type double
/// </summary>
/// <value>
/// degrees
/// </value>
public double Degrees
{
get
{
return _angle * DegreesPerRadian;
}
}
/// <summary>
/// Returns milliradians as type double
/// </summary>
/// <value>
/// milliradians
/// </value>
public double Milliradians
{
get
{
return _angle * MilliradiansPerRadian;
}
}
/// <summary>
/// Returns radians as type double
/// </summary>
/// <value>
/// radians
/// </value>
public double Radians
{
get
{
return _angle;
}
}
#endregion
#region creation methods
/// <summary>
/// Returns Angle object interpreting passed value as degrees
/// </summary>
/// <param name="degrees">degrees</param>
/// <returns></returns>
public static Angle FromDegrees(double degrees)
{
return new Angle(degrees / DegreesPerRadian);
}
/// <summary>
/// Returns Angle object interpreting passed value as milliradians
/// </summary>
/// <param name="milliradians">milliradians</param>
/// <returns></returns>
public static Angle FromMilliradians(double milliradians)
{
return new Angle(milliradians / MilliradiansPerRadian);
}
/// <summary>
/// Returns Angle object interpreting passed value as radians
/// </summary>
/// <param name="radians">radians</param>
/// <returns></returns>
public static Angle FromRadians(double radians)
{
return new Angle(radians);
}
#endregion
public override bool Equals(object obj)
{
Angle a = obj as Angle;
return (a == null) ? false : (this._angle == a._angle);
}
public override int GetHashCode()
{
return _angle.GetHashCode();
}
#region binary operators
// not implementing %, &, |, ^, <<, >>
public static Angle operator +(Angle left, Angle right)
{
if (null == left)
throw new ArgumentNullException("left", "Cannot add a null Angle");
if (null == right)
throw new ArgumentNullException("right", "Cannot add null Angle");
return new Angle(left._angle + right._angle);
}
public static Angle operator -(Angle left, Angle right)
{
if (null == left)
throw new ArgumentNullException("left", "Cannot subtract a null Angle");
if (null == right)
throw new ArgumentNullException("right", "Cannot subtract a null Angle");
return new Angle(left._angle - right._angle);
}
public static Angle operator *(Angle angle, double scalar)
{
if (null == angle)
throw new ArgumentNullException("angle", "Cannot multiply a null Angle");
return new Angle(angle._angle * scalar);
}
public static Angle operator *(double scalar, Angle angle)
{
if (null == angle)
throw new ArgumentNullException("angle", "Cannot multiply a null Angle");
return new Angle(scalar * angle._angle);
}
public static Angle operator /(Angle angle, double scalar)
{
if (null == angle)
throw new ArgumentNullException("angle", "Cannot divide a null Angle");
if (0.0 == scalar)
throw new DivideByZeroException("Cannot divide Angle by 0");
return new Angle(angle._angle / scalar);
}
#endregion
#region comparison operators
public static bool operator ==(Angle left, Angle right)
{
bool bReturn = false;
if (object.ReferenceEquals(left, null))
{
if (object.ReferenceEquals(right, null))
{
//both are null, so we are ==
bReturn = true;
}
}
else
{
if (!object.ReferenceEquals(left, null) &&
!object.ReferenceEquals(right, null))
{
bReturn = left._angle == right._angle;
}
}
return bReturn;
}
public static bool operator !=(Angle left, Angle right)
{
return !(left == right);
}
public static bool operator <(Angle left, Angle right)
{
if (null == left)
throw new ArgumentNullException("left", "Cannot compare null Angle");
if (null == right)
throw new ArgumentNullException("right", "Cannot compare null Angle");
return (left._angle < right._angle);
}
public static bool operator >(Angle left, Angle right)
{
if (null == left)
throw new ArgumentNullException("left", "Cannot compare null Angle");
if (null == right)
throw new ArgumentNullException("right", "Cannot compare null Angle");
return (left._angle > right._angle);
}
public static bool operator <=(Angle left, Angle right)
{
if (null == left)
throw new ArgumentNullException("left", "Cannot compare null Angle");
if (null == right)
throw new ArgumentNullException("right", "Cannot compare null Angle");
return (left._angle <= right._angle);
}
public static bool operator >=(Angle left, Angle right)
{
if (null == left)
throw new ArgumentNullException("left", "Cannot compare null Angle");
if (null == right)
throw new ArgumentNullException("right", "Cannot compare null Angle");
return (left._angle >= right._angle);
}
#endregion
#region operators with other classes
/// <summary>
/// Implements the operator / for AngularVelocity = Angle / PrecisionTimeSpan
/// </summary>
/// <param name="velocity">The angle.</param>
/// <param name="time">The time.</param>
/// <returns>
/// AngularVelocity
/// </returns>
public static AngularVelocity operator /(Angle angle, PrecisionTimeSpan time)
{
if (null == angle)
throw new ArgumentNullException("angle", "Cannot divide with null Angle");
if (null == time)
throw new ArgumentNullException("time", "Cannot divide with null PrecisionTimeSpan");
if (0.0 == time.Milliseconds)
throw new DivideByZeroException("Cannot divide angle by 0 time");
return AngularVelocity.FromRadiansPerSec(angle.Radians / time.Seconds);
}
/// <summary>
/// Implements the operator / for PrecisionTimeSpan = Angle / AngularVelocity
/// </summary>
/// <param name="velocity">The angle.</param>
/// <param name="time">The velocity.</param>
/// <returns>
/// PrecisionTimeSpan
/// </returns>
public static PrecisionTimeSpan operator /(Angle angle, AngularVelocity velocity)
{
if (null == angle)
throw new ArgumentNullException("angle", "Cannot divide with null Angle");
if (null == velocity)
throw new ArgumentNullException("velocity", "Cannot divide with null AngularVelocity");
if (0.0 == velocity.RadiansPerSec)
throw new DivideByZeroException("Cannot divide angle by 0 angular velocity");
return PrecisionTimeSpan.FromSeconds(angle.Radians / velocity.RadiansPerSec);
}
#endregion
#region parsing
public static Angle Parse(string s)
{
return Common.Parse(s, _unitInfo);
}
public static bool TryParse(string s, out Angle value)
{
try
{
value = Angle.Parse(s);
return true;
}
catch (Exception)
{
value = null;
return false;
}
}
#endregion
/// <summary>
/// Returns a string appended with default units (e.g. "1.23 m/sec^2").
/// </summary>
/// <returns>
/// A string that represents this instance
/// </returns>
public override string ToString()
{
return ToString(DefaultUnits);
}
/// <summary>
/// overload that returns a string appended with specified units (e.g. "1.23 ft/sec^2").
/// </summary>
/// <param name="units"></param>
/// <returns></returns>
public string ToString(Unit units)
{
double value = (double)_unitInfo[units].PropertyGetter.Invoke(this, null);
return $"{value} {_unitInfo[units].Abbreviation[0]}";
}
}
}

View File

@@ -0,0 +1,383 @@
using System;
using System.Runtime.Serialization;
using System.Diagnostics.CodeAnalysis;
using System.Collections.Generic;
namespace Raytheon.Units
{
/// <summary>
/// This class represents a velocity.
///
/// It has no constructors. Instead, it provides multiple methods for creating objects of this
/// type. Those methods are of the form FromXXX, where XXX is a unit (e.g. FromRadiansPerSecSqrd).
///
/// Properties (e.g. RadiansPerSecSqrd) are provided to convert the value to other units and
/// return as type double.
///
/// Methods (operator overloads) are provided to perform calculations with related types (e.g.
/// Angle, AngularVelocity).
/// </summary>
[Serializable]
[DataContract]
public class AngularAcceleration
{
public enum Unit
{
DegreesPerSecSqrd,
RadiansPerSecSqrd,
MilliradiansPerSecSqrd
}
public static IDictionary<Unit, List<string>> UnitAbbreviations = new Dictionary<Unit, List<string>>()
{
{Unit.DegreesPerSecSqrd, new List<string>(){ "deg/sec^2" } },
{Unit.MilliradiansPerSecSqrd, new List<string>(){ "mrad/sec^2" } },
{Unit.RadiansPerSecSqrd, new List<string>(){ "rad/sec^2" } }
};
private const Unit DefaultUnits = Unit.RadiansPerSecSqrd;
private const double DegreesPerRadian = 180 / Math.PI;
[DataMember(Name = "AngularAcceleration", IsRequired = true)]
private double _acceleration; // radians/seconds^2
// map: unit => abbreviation, conversion method and property
private static IDictionary<Unit, UnitInfo<AngularAcceleration>> _unitInfo = new Dictionary<Unit, UnitInfo<AngularAcceleration>>()
{
{ Unit.DegreesPerSecSqrd, new UnitInfo<AngularAcceleration>(UnitAbbreviations[Unit.DegreesPerSecSqrd], FromDegreesPerSecSqrd, typeof(AngularAcceleration).GetProperty("DegreesPerSecSqrd").GetGetMethod()) },
{ Unit.MilliradiansPerSecSqrd, new UnitInfo<AngularAcceleration>(UnitAbbreviations[Unit.MilliradiansPerSecSqrd], FromMilliradiansPerSecSqrd, typeof(AngularAcceleration).GetProperty("MilliradiansPerSecSqrd").GetGetMethod()) },
{ Unit.RadiansPerSecSqrd, new UnitInfo<AngularAcceleration>(UnitAbbreviations[Unit.RadiansPerSecSqrd], FromRadiansPerSecSqrd, typeof(AngularAcceleration).GetProperty("RadiansPerSecSqrd").GetGetMethod()) }
};
/// <summary>
/// Prevents a default instance of the <see cref="AngularAcceleration"/> class from being created.
/// Use FromXXX methods to create objects of this type.
/// </summary>
/// <exception cref="System.Exception">No one should be calling this, it is only here to prevent users from creating default object</exception>
private AngularAcceleration()
{
throw new InvalidOperationException("No one should be calling this, it is only here to prevent users from creating default object");
}
/// <summary>
/// ctor used by this class to create objects in FromXXX methods
/// </summary>
/// <param name="acceleration">The acceleration - radians/sec^2.</param>
private AngularAcceleration(double acceleration)
{
_acceleration = acceleration;
}
#region conversion properties
/// <summary>
/// Returns degrees/sec^2 as type double
/// </summary>
/// <value>
/// degrees/sec^2
/// </value>
public double DegreesPerSecSqrd
{
get { return _acceleration * DegreesPerRadian; }
}
/// <summary>
/// Returns milliradians/sec^2 as type double
/// </summary>
/// <value>
/// milliradians/sec^2
/// </value>
public double MilliradiansPerSecSqrd
{
get { return _acceleration * 1000; }
}
/// <summary>
/// Returns radians/sec^2 as type double
/// </summary>
/// <value>
/// radians/sec^2
/// </value>
public double RadiansPerSecSqrd
{
get { return _acceleration; }
}
#endregion
#region creation methods
/// <summary>
/// Returns AngularAcceleration object interpreting passed value as degrees/sec
/// </summary>
/// <param name="degreesPerSecSqrd">degrees/sec</param>
/// <returns></returns>
public static AngularAcceleration FromDegreesPerSecSqrd(double degreesPerSecSqrd)
{
return new AngularAcceleration(degreesPerSecSqrd / DegreesPerRadian);
}
/// <summary>
/// Returns AngularAcceleration object interpreting passed value as radians/sec^2
/// </summary>
/// <param name="milliradiansPerSecSqrd">radians/sec^2</param>
/// <returns></returns>
public static AngularAcceleration FromMilliradiansPerSecSqrd(double milliradiansPerSecSqrd)
{
return new AngularAcceleration(milliradiansPerSecSqrd / 1000);
}
/// <summary>
/// Returns AngularAcceleration object interpreting passed value as radians/sec^2
/// </summary>
/// <param name="radiansPerSecSqrd">radians/sec^2</param>
/// <returns></returns>
public static AngularAcceleration FromRadiansPerSecSqrd(double radiansPerSecSqrd)
{
return new AngularAcceleration(radiansPerSecSqrd);
}
#endregion
public override bool Equals(object obj)
{
AngularAcceleration a = obj as AngularAcceleration;
return (a == null) ? false : (this._acceleration == a._acceleration);
}
public override int GetHashCode()
{
return _acceleration.GetHashCode();
}
#region binary operators
// not implementing %, &, |, ^, <<, >>
public static AngularAcceleration operator +(AngularAcceleration left, AngularAcceleration right)
{
if (null == left)
throw new ArgumentNullException("left", "Cannot add a null AngularAcceleration");
if (null == right)
throw new ArgumentNullException("right", "Cannot add null AngularAcceleration");
return new AngularAcceleration(left._acceleration + right._acceleration);
}
public static AngularAcceleration operator -(AngularAcceleration left, AngularAcceleration right)
{
if (null == left)
throw new ArgumentNullException("left", "Cannot subtract a null AngularAcceleration");
if (null == right)
throw new ArgumentNullException("right", "Cannot subtract null AngularAcceleration");
return new AngularAcceleration(left._acceleration - right._acceleration);
}
public static AngularAcceleration operator *(AngularAcceleration acceleration, double scalar)
{
if (null == acceleration)
throw new ArgumentNullException("acceleration", "Cannot multiply a null AngularAcceleration");
return new AngularAcceleration(acceleration._acceleration * scalar);
}
public static AngularAcceleration operator *(double scalar, AngularAcceleration acceleration)
{
if (null == acceleration)
throw new ArgumentNullException("acceleration", "Cannot multiply a null AngularAcceleration");
return new AngularAcceleration(scalar * acceleration._acceleration);
}
public static AngularAcceleration operator /(AngularAcceleration acceleration, double scalar)
{
if (null == acceleration)
throw new ArgumentNullException("acceleration", "Cannot divide a null AngularAcceleration");
if (0.0 == scalar)
throw new DivideByZeroException("Cannot divide Angular Acceleration by 0");
return new AngularAcceleration(acceleration._acceleration / scalar);
}
#endregion
#region comparison operators
public static bool operator ==(AngularAcceleration left, AngularAcceleration right)
{
bool bReturn = false;
if (object.ReferenceEquals(left, null))
{
if (object.ReferenceEquals(right, null))
{
//both are null, so we are ==
bReturn = true;
}
}
else
{
if (!object.ReferenceEquals(left, null) &&
!object.ReferenceEquals(right, null))
{
bReturn = left._acceleration == right._acceleration;
}
}
return bReturn;
}
public static bool operator !=(AngularAcceleration left, AngularAcceleration right)
{
return !(left == right);
}
public static bool operator <(AngularAcceleration left, AngularAcceleration right)
{
if (null == left)
throw new ArgumentNullException("left", "Cannot compare null AngularAcceleration");
if (null == right)
throw new ArgumentNullException("right", "Cannot compare null AngularAcceleration");
return left._acceleration < right._acceleration;
}
public static bool operator >(AngularAcceleration left, AngularAcceleration right)
{
if (null == left)
throw new ArgumentNullException("left", "Cannot compare null AngularAcceleration");
if (null == right)
throw new ArgumentNullException("right", "Cannot compare null AngularAcceleration");
return left._acceleration > right._acceleration;
}
public static bool operator <=(AngularAcceleration left, AngularAcceleration right)
{
if (null == left)
throw new ArgumentNullException("left", "Cannot compare null AngularAcceleration");
if (null == right)
throw new ArgumentNullException("right", "Cannot compare null AngularAcceleration");
return left._acceleration <= right._acceleration;
}
public static bool operator >=(AngularAcceleration left, AngularAcceleration right)
{
if (null == left)
throw new ArgumentNullException("left", "Cannot compare null AngularAcceleration");
if (null == right)
throw new ArgumentNullException("right", "Cannot compare null AngularAcceleration");
return left._acceleration >= right._acceleration;
}
#endregion
#region operators with other classes
/// <summary>
/// Implements the operator * for AngularVelocity = AngularAcceleration * PrecisionTimeSpan
/// </summary>
/// <param name="acceleration">The velocity.</param>
/// <param name="time">The time.</param>
/// <returns>
/// Angle
/// </returns>
public static AngularVelocity operator *(AngularAcceleration acceleration, PrecisionTimeSpan time)
{
if (null == acceleration)
throw new ArgumentNullException("acceleration", "Cannot multiply with null AngularAcceleration");
if (null == time)
throw new ArgumentNullException("time", "Cannot multiply with null PrecisionTimeSpan");
return AngularVelocity.FromRadiansPerSec(acceleration.RadiansPerSecSqrd * time.Seconds);
}
/// <summary>
/// Implements the operator * for AngularVelocity = PrecisionTimeSpan * AngularAcceleration
/// </summary>
/// <param name="acceleration">The acceleration.</param>
/// <param name="time">The time.</param>
/// <returns>
/// AngularVelocity
/// </returns>
public static AngularVelocity operator *(PrecisionTimeSpan time, AngularAcceleration acceleration)
{
if (null == acceleration)
throw new ArgumentNullException("acceleration", "Cannot multiply with null AngularAcceleration");
if (null == time)
throw new ArgumentNullException("time", "Cannot multiply with null PrecisionTimeSpan");
return AngularVelocity.FromRadiansPerSec(time.Seconds * acceleration.RadiansPerSecSqrd);
}
#endregion
#region parsing
public static AngularAcceleration Parse(string s)
{
return Common.Parse(s, _unitInfo);
}
public static bool TryParse(string s, out AngularAcceleration value)
{
try
{
value = AngularAcceleration.Parse(s);
return true;
}
catch (Exception)
{
value = null;
return false;
}
}
#endregion
/// <summary>
/// Returns a string appended with default units (e.g. "1.23 deg/sec^2").
/// </summary>
/// <returns>
/// A string that represents this instance
/// </returns>
public override string ToString()
{
return ToString(DefaultUnits);
}
/// <summary>
/// overload that returns a string appended with specified units (e.g. "1.23 deg/sec^2").
/// </summary>
/// <param name="units"></param>
/// <returns></returns>
public string ToString(Unit units)
{
double value = (double)_unitInfo[units].PropertyGetter.Invoke(this, null);
return $"{value} {_unitInfo[units].Abbreviation[0]}";
}
}
}

View File

@@ -0,0 +1,430 @@
using System;
using System.Text;
using System.Runtime.Serialization;
using System.Diagnostics.CodeAnalysis;
using System.Collections.Generic;
namespace Raytheon.Units
{
/// <summary>
/// This class represents a velocity.
///
/// It has no constructors. Instead, it provides multiple methods for creating objects of this
/// type. Those methods are of the form FromXXX, where XXX is a unit (e.g. FromRadiansPerSec).
///
/// Properties (e.g. RadiansPerSec) are provided to convert the value to other units and return
/// as type double.
///
/// Methods (operator overloads) are provided to perform calculations with related types (e.g.
/// Angle, AngularAcceleration).
/// </summary>
[Serializable]
[DataContract]
public class AngularVelocity
{
public enum Unit
{
DegreesPerSec,
RadiansPerSec,
MilliradiansPerSec
}
public static IDictionary<Unit, List<string>> UnitAbbreviations = new Dictionary<Unit, List<string>>()
{
{Unit.DegreesPerSec, new List<string>(){ "deg/sec" } },
{Unit.RadiansPerSec, new List<string>(){ "rad/sec" } },
{Unit.MilliradiansPerSec, new List<string>(){ "mrad/sec" } },
};
private const Unit DefaultUnits = Unit.RadiansPerSec;
private const double DegreesPerRadian = 180 / Math.PI;
[DataMember(Name = "AngularVelocity", IsRequired = true)]
private double _velocity; // radians/second
// map: unit => abbreviation, conversion method and property
private static IDictionary<Unit, UnitInfo<AngularVelocity>> _unitInfo = new Dictionary<Unit, UnitInfo<AngularVelocity>>()
{
{ Unit.DegreesPerSec, new UnitInfo<AngularVelocity>(UnitAbbreviations[Unit.DegreesPerSec], FromDegreesPerSec, typeof(AngularVelocity).GetProperty("DegreesPerSec").GetGetMethod()) },
{ Unit.MilliradiansPerSec, new UnitInfo<AngularVelocity>(UnitAbbreviations[Unit.MilliradiansPerSec], FromMilliradiansPerSec, typeof(AngularVelocity).GetProperty("MilliradiansPerSec").GetGetMethod()) },
{ Unit.RadiansPerSec, new UnitInfo<AngularVelocity>(UnitAbbreviations[Unit.RadiansPerSec], FromRadiansPerSec, typeof(AngularVelocity).GetProperty("RadiansPerSec").GetGetMethod()) }
};
/// <summary>
/// Prevents a default instance of the <see cref="AngularVelocity"/> class from being created.
/// Use FromXXX methods to create objects of this type.
/// </summary>
/// <exception cref="System.Exception">No one should be calling this, it is only here to prevent users from creating default object</exception>
private AngularVelocity()
{
throw new InvalidOperationException("No one should be calling this, it is only here to prevent users from creating default object");
}
/// <summary>
/// ctor used by this class to create objects in FromXXX methods
/// </summary>
/// <param name="velocity">The velocity - radians/sec.</param>
private AngularVelocity(double velocity)
{
_velocity = velocity;
}
#region conversion properties
/// <summary>
/// Returns degrees/sec as type double
/// </summary>
/// <value>
/// degrees/sec
/// </value>
public double DegreesPerSec
{
get { return _velocity * DegreesPerRadian; }
}
/// <summary>
/// Returns degrees/sec as type double
/// </summary>
/// <value>
/// degrees/sec
/// </value>
public double MilliradiansPerSec
{
get { return _velocity * 1000; }
}
/// <summary>
/// Returns radians/sec as type double
/// </summary>
/// <value>
/// radians/sec
/// </value>
public double RadiansPerSec
{
get { return _velocity; }
}
#endregion
#region creation methods
/// <summary>
/// Returns AngularVelocity object interpreting passed value as degrees/sec
/// </summary>
/// <param name="degreesPerSec">degrees/sec</param>
/// <returns></returns>
public static AngularVelocity FromDegreesPerSec(double degreesPerSec)
{
return new AngularVelocity(degreesPerSec / DegreesPerRadian);
}
/// <summary>
/// Returns AngularVelocity object interpreting passed value as milliradians/sec
/// </summary>
/// <param name="milliradiansPerSec">milliradians/sec</param>
/// <returns></returns>
public static AngularVelocity FromMilliradiansPerSec(double milliradiansPerSec)
{
return new AngularVelocity(milliradiansPerSec / 1000);
}
/// <summary>
/// Returns AngularVelocity object interpreting passed value as radians/sec
/// </summary>
/// <param name="radiansPerSec">radians/sec</param>
/// <returns></returns>
public static AngularVelocity FromRadiansPerSec(double radiansPerSec)
{
return new AngularVelocity(radiansPerSec);
}
#endregion
public override bool Equals(object obj)
{
AngularVelocity v = obj as AngularVelocity;
return (v == null) ? false : (this._velocity == v._velocity);
}
public override int GetHashCode()
{
return _velocity.GetHashCode();
}
#region binary operators
// not implementing %, &, |, ^, <<, >>
public static AngularVelocity operator +(AngularVelocity left, AngularVelocity right)
{
if (null == left)
throw new ArgumentNullException("left", "Cannot add a null AngularVelocity");
if (null == right)
throw new ArgumentNullException("right", "Cannot add null AngularVelocity");
return new AngularVelocity(left._velocity + right._velocity);
}
public static AngularVelocity operator -(AngularVelocity left, AngularVelocity right)
{
if (null == left)
throw new ArgumentNullException("left", "Cannot subtract a null AngularVelocity");
if (null == right)
throw new ArgumentNullException("right", "Cannot subtract a null AngularVelocity");
return new AngularVelocity(left._velocity - right._velocity);
}
public static AngularVelocity operator *(AngularVelocity velocity, double scalar)
{
if (null == velocity)
throw new ArgumentNullException("velocity", "Cannot multiply a null AngularVelocity");
return new AngularVelocity(velocity._velocity * scalar);
}
public static AngularVelocity operator *(double scalar, AngularVelocity velocity)
{
if (null == velocity)
throw new ArgumentNullException("velocity", "Cannot multiply a null AngularVelocity");
return new AngularVelocity(scalar * velocity._velocity);
}
public static AngularVelocity operator /(AngularVelocity velocity, double scalar)
{
if (null == velocity)
throw new ArgumentNullException("velocity", "Cannot divide a null AngularVelocity");
if (0.0 == scalar)
throw new DivideByZeroException("Cannot divide Angular Velocity by 0");
return new AngularVelocity(velocity._velocity / scalar);
}
#endregion
#region comparison operators
public static bool operator ==(AngularVelocity left, AngularVelocity right)
{
bool bReturn = false;
if (object.ReferenceEquals(left, null))
{
if (object.ReferenceEquals(right, null))
{
//both are null, so we are ==
bReturn = true;
}
}
else
{
if (!object.ReferenceEquals(left, null) &&
!object.ReferenceEquals(right, null))
{
bReturn = left._velocity == right._velocity;
}
}
return bReturn;
}
public static bool operator !=(AngularVelocity left, AngularVelocity right)
{
return !(left == right);
}
public static bool operator <(AngularVelocity left, AngularVelocity right)
{
if (null == left)
throw new ArgumentNullException("left", "Cannot compare null AngularVelocity");
if (null == right)
throw new ArgumentNullException("right", "Cannot compare null AngularVelocity");
return (left._velocity < right._velocity);
}
public static bool operator >(AngularVelocity left, AngularVelocity right)
{
if (null == left)
throw new ArgumentNullException("left", "Cannot compare null AngularVelocity");
if (null == right)
throw new ArgumentNullException("right", "Cannot compare null AngularVelocity");
return (left._velocity > right._velocity);
}
public static bool operator <=(AngularVelocity left, AngularVelocity right)
{
if (null == left)
throw new ArgumentNullException("left", "Cannot compare null AngularVelocity");
if (null == right)
throw new ArgumentNullException("right", "Cannot compare null AngularVelocity");
return (left._velocity <= right._velocity);
}
public static bool operator >=(AngularVelocity left, AngularVelocity right)
{
if (null == left)
throw new ArgumentNullException("left", "Cannot compare null AngularVelocity");
if (null == right)
throw new ArgumentNullException("right", "Cannot compare null AngularVelocity");
return (left._velocity >= right._velocity);
}
#endregion
#region operators with other classes
/// <summary>
/// Implements the operator * for Angle = AngularVelocity * PrecisionTimeSpan
/// </summary>
/// <param name="velocity">The velocity.</param>
/// <param name="time">The time.</param>
/// <returns>
/// Angle
/// </returns>
public static Angle operator *(AngularVelocity velocity, PrecisionTimeSpan time)
{
if (null == velocity)
throw new ArgumentNullException("velocity", "Cannot multiply with null AngularVelocity");
if (null == time)
throw new ArgumentNullException("time", "Cannot multiply with null PrecisionTimeSpan");
return Angle.FromRadians(velocity.RadiansPerSec * time.Seconds);
}
/// <summary>
/// Implements the operator * for Angle = PrecisionTimeSpan * AngularVelocity
/// </summary>
/// <param name="time">The time.</param>
/// <param name="velocity">The velocity.</param>
/// <returns>
/// Angle
/// </returns>
public static Angle operator *(PrecisionTimeSpan time, AngularVelocity velocity)
{
if (null == velocity)
throw new ArgumentNullException("velocity", "Cannot multiply with null AngularVelocity");
if (null == time)
throw new ArgumentNullException("time", "Cannot multiply with null PrecisionTimeSpan");
return Angle.FromRadians(time.Seconds * velocity.RadiansPerSec);
}
/// <summary>
/// Implements the operator / for AngularAcceleration = AngularVelocity / PrecisionTimeSpan
/// </summary>
/// <param name="velocity">The velocity.</param>
/// <param name="time">The time.</param>
/// <returns>
/// AngularAcceleration
/// </returns>
public static AngularAcceleration operator /(AngularVelocity velocity, PrecisionTimeSpan time)
{
if (null == velocity)
throw new ArgumentNullException("velocity", "Cannot divide with null AngularVelocity");
if (null == time)
throw new ArgumentNullException("time", "Cannot divide with null PrecisionTimeSpan");
if (0.0 == time.Milliseconds)
throw new DivideByZeroException("Cannot divide Angular Velocity by 0 time");
return AngularAcceleration.FromRadiansPerSecSqrd(velocity.RadiansPerSec / time.Seconds);
}
/// <summary>
/// Implements the operator / for PrecisionTimeSpan = AngularVelocity / AngularAcceleration
/// </summary>
/// <param name="velocity">The velocity.</param>
/// <param name="acceleration">The acceleration.</param>
/// <returns>
/// Angle
/// </returns>
public static PrecisionTimeSpan operator /(AngularVelocity velocity, AngularAcceleration acceleration)
{
if (null == velocity)
throw new ArgumentNullException("velocity", "Cannot divide with null AngularVelocity");
if (null == acceleration)
throw new ArgumentNullException("acceleration", "Cannot divide with null AngularAcceleration");
if (0.0 == acceleration.RadiansPerSecSqrd)
throw new DivideByZeroException("Cannot divide Angular Velocity by 0 Angular Acceleration");
return PrecisionTimeSpan.FromSeconds(velocity.RadiansPerSec / acceleration.RadiansPerSecSqrd);
}
#endregion
#region parsing
public static AngularVelocity Parse(string s)
{
return Common.Parse(s, _unitInfo);
}
public static bool TryParse(string s, out AngularVelocity value)
{
try
{
value = AngularVelocity.Parse(s);
return true;
}
catch (Exception)
{
value = null;
return false;
}
}
#endregion
/// <summary>
/// Returns a string appended with default units (e.g. "1.23 m/sec^2").
/// </summary>
/// <returns>
/// A string that represents this instance
/// </returns>
public override string ToString()
{
return ToString(DefaultUnits);
}
/// <summary>
/// overload that returns a string appended with specified units (e.g. "1.23 ft/sec^2").
/// </summary>
/// <param name="units"></param>
/// <returns></returns>
public string ToString(Unit units)
{
double value = (double)_unitInfo[units].PropertyGetter.Invoke(this, null);
return $"{value} {_unitInfo[units].Abbreviation[0]}";
}
}
}

View File

@@ -0,0 +1,83 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text.RegularExpressions;
namespace Raytheon.Units
{
/// <summary>
/// Contains info related to a unit: to parse, print, and convert values
/// </summary>
internal class UnitInfo<T>
{
public UnitInfo( List<string> abbreviation,
Func<double, T> conversionMethod,
MethodInfo propertyGetter )
{
Abbreviation = abbreviation;
ConversionMethod = conversionMethod;
PropertyGetter = propertyGetter;
}
/// <summary>
/// standard text abbreviation for this unit
/// </summary>
public List<string> Abbreviation { get; private set; }
/// <summary>
/// method for converting string to this unit
/// </summary>
public Func<double, T> ConversionMethod { get; private set; }
/// <summary>
/// get method for the property associated with this unit
/// </summary>
public MethodInfo PropertyGetter { get; set; }
}
internal class Common
{
/// <summary>
/// Converts a string that represents a number with a unit to the actual
/// unit type.
/// </summary>
/// <typeparam name="E">Enumeration of the Unit abbreviation</typeparam>
/// <typeparam name="T">The actual unit type, i.e Current</typeparam>
/// <param name="s">String that represents a unit value, i.e 1.23 Amps</param>
/// <param name="unitInfo">Look up table for how to convert the units</param>
/// <returns>
/// The converted number to the correct unit type. If unable to parse, will return the first
/// <see cref="UnitInfo{T}.ConversionMethod"/> with a value of <see cref="double.NaN"/>
/// </returns>
public static T Parse<E, T>( string s, IDictionary<E, UnitInfo<T>> unitInfo )
{
const string FloatingPointPattern = @"([-+]?[0-9]+(\.[0-9]+)?([Ee][+-][0-9]+)?)";
const string AbbreviationPattern = @"([\w/\^]*)";
string pattern = FloatingPointPattern + @"\s*" + AbbreviationPattern;
Regex regEx = new Regex( pattern );
Match match = regEx.Match( s );
if(!match.Success || match.Groups.Count == 0 )
{
throw new FormatException( $"UUnknown value : {s}" );
}
string abbreviation = match.Groups[match.Groups.Count - 1].Value;
IEnumerable<UnitInfo<T>> x = unitInfo.Where( kvp => kvp.Value.Abbreviation.Contains( abbreviation, StringComparer.CurrentCultureIgnoreCase ) )
.Select( kvp => kvp.Value );
// abbreviation not found?
if ( x.Count( ) == 0 )
{
throw new FormatException( $"Unknown units: '{abbreviation}'" );
}
double value = double.Parse( match.Groups[1].Value );
return x.First( ).ConversionMethod( value );
}
}
}

View File

@@ -0,0 +1,14 @@
namespace Raytheon.Units
{
public class Constants
{
// SI Prefixes decimal value
public const double GIGA = 1e9;
public const double MEGA = 1e6;
public const double KILO = 1e3;
public const double CENTI = 1e-2;
public const double MILLI = 1e-3;
public const double MICRO = 1e-6;
public const double NANO = 1e-9;
}
}

View File

@@ -0,0 +1,342 @@
using System;
using System.Text;
using System.Runtime.Serialization;
using System.Diagnostics.CodeAnalysis;
using System.Collections.Generic;
namespace Raytheon.Units
{
/// <summary>
/// This class represents an electrical current.
///
/// It has no constructors. Instead, it provides multiple methods for creating objects of this
/// type. Those methods are of the form FromXXX, where XXX is a unit (e.g.
/// FromAmps).
///
/// Properties (e.g. Amps) are provided to convert the value to other units and return as type
/// double.
///
/// Methods (operator overloads) are provided to perform calculations with related types (e.g.
/// Voltage, Resistance).
/// </summary>
[Serializable]
[DataContract]
public class Current
{
public enum Unit
{
Amps,
Milliamps
}
public static IDictionary<Unit, List<string>> UnitAbbreviations = new Dictionary<Unit, List<string>>()
{
{Unit.Amps, new List<string>(){ "A" } },
{Unit.Milliamps, new List<string>(){ "mA" } },
};
private const Unit DefaultUnits = Unit.Amps;
private const int MilliampsPerAmp = 1000;
[DataMember(Name = "Current", IsRequired = true)]
private double _current; // amps
// map: unit => abbreviation, conversion method and property
private static IDictionary<Unit, UnitInfo<Current>> _unitInfo = new Dictionary<Unit, UnitInfo<Current>>()
{
{ Unit.Amps, new UnitInfo<Current>(UnitAbbreviations[Unit.Amps], FromAmps, typeof(Current).GetProperty("Amps").GetGetMethod()) },
{ Unit.Milliamps, new UnitInfo<Current>(UnitAbbreviations[Unit.Milliamps], FromMilliamps, typeof(Current).GetProperty("Milliamps").GetGetMethod()) }
};
/// <summary>
/// Prevents a default instance of the <see cref="Current"/> class from being created.
/// Use FromXXX methods to create objects of this type.
/// </summary>
/// <exception cref="System.Exception">No one should be calling this, it is only here to prevent users from creating default object</exception>
private Current()
{
throw new InvalidOperationException("No one should be calling this, it is only here to prevent users from creating default object");
}
/// <summary>
/// ctor used by this class to create objects in FromXXX methods
/// </summary>
/// <param name="current">The current - amps.</param>
private Current(double current)
{
_current = current;
}
#region conversion properties
/// <summary>
/// Returns amps as type double
/// </summary>
/// <value>
/// amps
/// </value>
public double Amps
{
get { return _current; }
}
/// <summary>
/// Returns milliamps as type double
/// </summary>
/// <value>
/// milliamps
/// </value>
public double Milliamps
{
get { return _current * MilliampsPerAmp; }
}
#endregion
#region creation methods
/// <summary>
/// Returns Current object interpreting passed value as amps
/// </summary>
/// <param name="amps">amps</param>
/// <returns></returns>
public static Current FromAmps(double amps)
{
return new Current(amps);
}
/// <summary>
/// Returns Current object interpreting passed value as milliamps
/// </summary>
/// <param name="milliamps">milliamps</param>
/// <returns></returns>
public static Current FromMilliamps(double milliamps)
{
return new Current(milliamps / MilliampsPerAmp);
}
#endregion
public override bool Equals(object obj)
{
Current c = obj as Current;
return (c == null) ? false : (this._current == c._current);
}
public override int GetHashCode()
{
return _current.GetHashCode();
}
#region binary operators
// not implementing %, &, |, ^, <<, >>
public static Current operator +(Current left, Current right)
{
if (null == left)
throw new ArgumentNullException("left", "Cannot add a null Current");
if (null == right)
throw new ArgumentNullException("right", "Cannot add null Current");
return new Current(left._current + right._current);
}
public static Current operator -(Current left, Current right)
{
if (null == left)
throw new ArgumentNullException("left", "Cannot subtract a null Current");
if (null == right)
throw new ArgumentNullException("right", "Cannot subtract a null Current");
return new Current(left._current - right._current);
}
public static Current operator *(Current current, double scalar)
{
if (null == current)
throw new ArgumentNullException("current", "Cannot multiply a null Current");
return new Current(current._current * scalar);
}
public static Current operator *(double scalar, Current current)
{
if (null == current)
throw new ArgumentNullException("current", "Cannot multiply a null Current");
return new Current(scalar * current._current);
}
public static Current operator /(Current current, double scalar)
{
if (null == current)
throw new ArgumentNullException("current", "Cannot divide a null Current");
if (0.0 == scalar)
throw new DivideByZeroException("Cannot divide Current by 0");
return new Current(current._current / scalar);
}
#endregion
#region comparison operators
public static bool operator ==(Current left, Current right)
{
bool bReturn = false;
if (object.ReferenceEquals(left, null))
{
if (object.ReferenceEquals(right, null))
{
//both are null, so we are ==
bReturn = true;
}
}
else
{
if (!object.ReferenceEquals(left, null) &&
!object.ReferenceEquals(right, null))
{
bReturn = left._current == right._current;
}
}
return bReturn;
}
public static bool operator !=(Current left, Current right)
{
return !(left == right);
}
public static bool operator <(Current left, Current right)
{
if (null == left)
throw new ArgumentNullException("left", "Cannot compare null Current");
if (null == right)
throw new ArgumentNullException("right", "Cannot compare null Current");
return (left._current < right._current);
}
public static bool operator >(Current left, Current right)
{
if (null == left)
throw new ArgumentNullException("left", "Cannot compare null Current");
if (null == right)
throw new ArgumentNullException("right", "Cannot compare null Current");
return (left._current > right._current);
}
public static bool operator <=(Current left, Current right)
{
if (null == left)
throw new ArgumentNullException("left", "Cannot compare null Current");
if (null == right)
throw new ArgumentNullException("right", "Cannot compare null Current");
return (left._current <= right._current);
}
public static bool operator >=(Current left, Current right)
{
if (null == left)
throw new ArgumentNullException("left", "Cannot compare null Current");
if (null == right)
throw new ArgumentNullException("right", "Cannot compare null Current");
return (left._current >= right._current);
}
#endregion
#region operators with other classes
/// <summary>
/// Implements the operator * for Voltage = Current * Resistance
/// </summary>
/// <param name="current">The current.</param>
/// <param name="resistance">The resistance.</param>
/// <returns>
/// Voltage
/// </returns>
public static Voltage operator *(Current current, Resistance resistance)
{
if (null == current)
throw new ArgumentNullException("current", "Cannot multiply a null Current");
if (null == resistance)
throw new ArgumentNullException("resistance", "Cannot multiply null Resistance");
return Voltage.FromVolts(current.Amps * resistance.Ohms);
}
#endregion
#region parsing
public static Current Parse(string s)
{
return Common.Parse(s, _unitInfo);
}
public static bool TryParse(string s, out Current value)
{
try
{
value = Current.Parse(s);
return true;
}
catch (Exception)
{
value = null;
return false;
}
}
#endregion
/// <summary>
/// Returns a string appended with default units (e.g. "1.23 m/sec^2").
/// </summary>
/// <returns>
/// A string that represents this instance
/// </returns>
public override string ToString()
{
return ToString(DefaultUnits);
}
/// <summary>
/// overload that returns a string appended with specified units (e.g. "1.23 ft/sec^2").
/// </summary>
/// <param name="units"></param>
/// <returns></returns>
public string ToString(Unit units)
{
double value = (double)_unitInfo[units].PropertyGetter.Invoke(this, null);
return $"{value} {_unitInfo[units].Abbreviation[0]}";
}
}
}

View File

@@ -0,0 +1,322 @@
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Runtime.Serialization;
using System.Text;
namespace Raytheon.Units
{
/// <summary>
/// This class represents energy.
///
/// It has no constructors. Instead, it provides multiple methods for creating objects of this
/// type. Those methods are of the form FromXXX, where XXX is a unit (e.g. FromJoulesPerCmSqrd).
///
/// Properties (e.g. JoulesPerCmSqrd) are provided to convert the value to other units and return
/// as type double.
/// </summary>
[Serializable]
[DataContract]
public class Energy
{
public enum Unit
{
JoulesPerCmSqrd,
MillijoulesPerCmSqrd
}
public static IDictionary<Unit, List<string>> UnitAbbreviations = new Dictionary<Unit, List<string>>()
{
{Unit.JoulesPerCmSqrd, new List<string>(){ "J/cm^2" } },
{Unit.MillijoulesPerCmSqrd, new List<string>(){ "mJ/cm^2" } },
};
private const Unit DefaultUnits = Unit.JoulesPerCmSqrd;
[DataMember(Name = "Energy", IsRequired = true)]
private double _energy; // joules/centimeter^2
// map: unit => abbreviation, conversion method and property
private static IDictionary<Unit, UnitInfo<Energy>> _unitInfo = new Dictionary<Unit, UnitInfo<Energy>>()
{
{ Unit.JoulesPerCmSqrd, new UnitInfo<Energy>(UnitAbbreviations[Unit.JoulesPerCmSqrd], FromJoulesPerCmSqrd, typeof(Energy).GetProperty("JoulesPerCmSqrd").GetGetMethod()) },
{ Unit.MillijoulesPerCmSqrd, new UnitInfo<Energy>(UnitAbbreviations[Unit.MillijoulesPerCmSqrd], FromMillijoulesPerCmSqrd, typeof(Energy).GetProperty("MillijoulesPerCmSqrd").GetGetMethod()) }
};
/// <summary>
/// Prevents a default instance of the <see cref="Energy"/> class from being created.
/// Use FromXXX methods to create objects of this type.
/// </summary>
/// <exception cref="System.Exception">No one should be calling this, it is only here to prevent users from creating default object</exception>
private Energy()
{
throw new InvalidOperationException("No one should be calling this, it is only here to prevent users from creating default object");
}
/// <summary>
/// ctor used by this class to create objects in FromXXX methods
/// </summary>
/// <param name="energy">The energy - joules/cm^2.</param>
private Energy(double energy)
{
_energy = energy;
}
#region conversion properties
/// <summary>
/// Returns joules/cm^2 as type double
/// </summary>
/// <value>
/// joules/cm^2
/// </value>
public double JoulesPerCmSqrd
{
get { return _energy; }
}
/// <summary>
/// Returns joules/cm^2 as type double
/// </summary>
/// <value>
/// joules/cm^2
/// </value>
public double MillijoulesPerCmSqrd
{
get { return _energy * 1000; }
}
#endregion
#region creation methods
/// <summary>
/// Returns Energy object interpreting passed value as joules/cm^2
/// </summary>
/// <param name="joulesPerCmSqrd">joules/cm^2</param>
/// <returns></returns>
public static Energy FromJoulesPerCmSqrd(double joulesPerCmSqrd)
{
return new Energy(joulesPerCmSqrd);
}
/// <summary>
/// Returns Energy object interpreting passed value as joules/cm^2
/// </summary>
/// <param name="joulesPerCmSqrd">joules/cm^2</param>
/// <returns></returns>
public static Energy FromMillijoulesPerCmSqrd(double joulesPerCmSqrd)
{
return new Energy(joulesPerCmSqrd / 1000);
}
#endregion
public override bool Equals(object obj)
{
Energy e = obj as Energy;
return (e == null) ? false : (this._energy == e._energy);
}
public override int GetHashCode()
{
return _energy.GetHashCode();
}
#region binary operators
// not implementing %, &, |, ^, <<, >>
public static Energy operator +(Energy left, Energy right)
{
if (null == left)
throw new ArgumentNullException("left", "Cannot add a null Energy");
if (null == right)
throw new ArgumentNullException("right", "Cannot add null Energy");
return new Energy(left._energy + right._energy);
}
public static Energy operator -(Energy left, Energy right)
{
if (null == left)
throw new ArgumentNullException("left", "Cannot subtract a null Energy");
if (null == right)
throw new ArgumentNullException("right", "Cannot subtract a null Energy");
return new Energy(left._energy - right._energy);
}
public static Energy operator *(Energy energy, double scalar)
{
if (null == energy)
throw new ArgumentNullException("energy", "Cannot multiply a null Energy");
return new Energy(energy._energy * scalar);
}
public static Energy operator *(double scalar, Energy energy)
{
if (null == energy)
throw new ArgumentNullException("energy", "Cannot multiply a null Energy");
return new Energy(scalar * energy._energy);
}
public static Energy operator /(Energy energy, double scalar)
{
if (null == energy)
throw new ArgumentNullException("energy", "Cannot divide a null Energy");
if (0.0 == scalar)
throw new DivideByZeroException("Cannot divide Energy by 0");
return new Energy(energy._energy / scalar);
}
#endregion
#region comparison operators
public static bool operator ==(Energy left, Energy right)
{
bool bReturn = false;
if (object.ReferenceEquals(left, null))
{
if (object.ReferenceEquals(right, null))
{
//both are null, so we are ==
bReturn = true;
}
}
else
{
if (!object.ReferenceEquals(left, null) &&
!object.ReferenceEquals(right, null))
{
bReturn = left._energy == right._energy;
}
}
return bReturn;
}
public static bool operator !=(Energy left, Energy right)
{
return !(left == right);
}
public static bool operator <(Energy left, Energy right)
{
if (null == left)
throw new ArgumentNullException("left", "Cannot compare null Energy");
if (null == right)
throw new ArgumentNullException("right", "Cannot compare null Energy");
return (left._energy < right._energy);
}
public static bool operator >(Energy left, Energy right)
{
if (null == left)
throw new ArgumentNullException("left", "Cannot compare null Energy");
if (null == right)
throw new ArgumentNullException("right", "Cannot compare null Energy");
return (left._energy > right._energy);
}
public static bool operator <=(Energy left, Energy right)
{
if (null == left)
throw new ArgumentNullException("left", "Cannot compare null Energy");
if (null == right)
throw new ArgumentNullException("right", "Cannot compare null Energy");
return (left._energy <= right._energy);
}
public static bool operator >=(Energy left, Energy right)
{
if (null == left)
throw new ArgumentNullException("left", "Cannot compare null Energy");
if (null == right)
throw new ArgumentNullException("right", "Cannot compare null Energy");
return (left._energy >= right._energy);
}
#endregion
#region operators with other classes
// no operators right now
#endregion
#region parsing
public static Energy Parse(string s)
{
return Common.Parse(s, _unitInfo);
}
public static bool TryParse(string s, out Energy value)
{
try
{
value = Energy.Parse(s);
return true;
}
catch (Exception)
{
value = null;
return false;
}
}
#endregion
/// <summary>
/// Returns a string appended with default units (e.g. "1.23 m/sec^2").
/// </summary>
/// <returns>
/// A string that represents this instance
/// </returns>
public override string ToString()
{
return ToString(DefaultUnits);
}
/// <summary>
/// overload that returns a string appended with specified units (e.g. "1.23 ft/sec^2").
/// </summary>
/// <param name="units"></param>
/// <returns></returns>
public string ToString(Unit units)
{
double value = (double)_unitInfo[units].PropertyGetter.Invoke(this, null);
return $"{value} {_unitInfo[units].Abbreviation[0]}";
}
}
}

View File

@@ -0,0 +1,356 @@
//############################################################################//
// RAYTHEON PROPRIETARY: THIS DOCUMENT CONTAINS DATA OR INFORMATION
// PROPRIETARY TO RAYTHEON COMPANY AND IS RESTRICTED TO USE ONLY BY PERSONS
// AUTHORIZED BY RAYTHEON COMPANY IN WRITING TO USE IT. DISCLOSURE TO
// UNAUTHORIZED PERSONS WOULD LIKELY CAUSE SUBSTANTIAL COMPETITIVE HARM TO
// RAYTHEON COMPANY'S BUSINESS POSITION. NEITHER SAID DOCUMENT NOR ITS
// CONTENTS SHALL BE FURNISHED OR DISCLOSED TO OR COPIED OR USED BY PERSONS
// OUTSIDE RAYTHEON COMPANY WITHOUT THE EXPRESS WRITTEN APPROVAL OF RAYTHEON
// COMPANY.
//
// THIS PROPRIETARY NOTICE IS NOT APPLICABLE IF DELIVERED TO THE U.S. GOVERNMENT
//
// UNPUBLISHED WORK - COPYRIGHT RAYTHEON COMPANY.
//
// WARNING: THIS DOCUMENT CONTAINS TECHNICAL DATA AND / OR TECHNOLOGY WHOSE
// EXPORT OR DISCLOSURE TO NON-U.S. PERSONS, WHEREVER LOCATED, IS RESTRICTED
// BY THE INTERNATIONAL TRAFFIC IN ARMS REGULATIONS (ITAR) (22 C.F.R. SECTION
// 120-130) OR THE EXPORT ADMINISTRATION REGULATIONS (EAR) (15 C.F.R. SECTION
// 730-774). THIS DOCUMENT CANNOT BE EXPORTED (E.G., PROVIDED TO A SUPPLIER
// OUTSIDE OF THE UNITED STATES) OR DISCLOSED TO A NON-U.S. PERSON, WHEREVER
// LOCATED, UNTIL A FINAL JURISDICTION AND CLASSIFICATION DETERMINATION HAS
// BEEN COMPLETED AND APPROVED BY RAYTHEON, AND ANY REQUIRED U.S. GOVERNMENT
// APPROVALS HAVE BEEN OBTAINED. VIOLATIONS ARE SUBJECT TO SEVERE CRIMINAL
// PENALTIES.
//
// DOD 5220.22-M, INDUSTRIAL SECURITY MANUAL, CHAPTER 5, SECTION 1 THROUGH 9 :
// FOR CLASSIFIED DOCUMENTS FOLLOW THE PROCEDURES IN OR DOD 5200.1-R,
// INFORMATION SECURITY PROGRAM, CHAPTER 6. FOR UNCLASSIFIED, LIMITED DOCUMENTS
// DESTROY BY ANY METHOD THAT WILL PREVENT DISCLOSURE OF CONTENTS OR
// RECONSTRUCTION OF THE DOCUMENT.
//############################################################################//
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Runtime.Serialization;
using System.Text;
namespace Raytheon.Units
{
/// <summary>
/// This class represents a Flow Rate.
///
/// It has no constructors. Instead, it provides multiple methods for creating objects of this
/// type. Those methods are of the form FromXXX, where XXX is a unit (e.g. FromCubicMetersPerSecond).
///
/// Properties (e.g. CubicMetersPerSecond) are provided to convert the value to other units and return
/// as type double.
/// </summary>
[Serializable]
[DataContract]
public class FlowRate
{
public enum Unit
{
CubicMetersPerSecond,
CubicMetersPerMinute,
CubicMetersPerHour,
GallonsPerMinute
}
public static IDictionary<Unit, List<string>> UnitAbbreviations = new Dictionary<Unit, List<string>>()
{
{Unit.CubicMetersPerSecond, new List<string>(){ "m^3/s" } },
{Unit.CubicMetersPerMinute, new List<string>(){ "m^3/min" } },
{Unit.CubicMetersPerHour, new List<string>(){ "m^3/h" } },
{Unit.GallonsPerMinute, new List<string>(){ "gal/min" } },
};
private const Unit DefaultUnits = Unit.CubicMetersPerSecond;
private const double CubicMetersToGalPerSecMultipler = 15850;
private const int SecondsPerMinute = 60;
private const int SecondsPerHour = 3600;
[DataMember(Name = "CubicMetersPerSecond", IsRequired = true)]
private readonly double _flowRate;
// map: unit => abbreviation, conversion method and property
private static readonly IDictionary<Unit, UnitInfo<FlowRate>> _unitInfo = new Dictionary<Unit, UnitInfo<FlowRate>>()
{
{ Unit.CubicMetersPerSecond, new UnitInfo<FlowRate>(UnitAbbreviations[Unit.CubicMetersPerSecond], FromCubicMetersPerSecond, typeof(FlowRate).GetProperty("CubicMetersPerSecond").GetGetMethod()) },
{ Unit.CubicMetersPerMinute, new UnitInfo<FlowRate>(UnitAbbreviations[Unit.CubicMetersPerMinute], FromCubicMetersPerMinute, typeof(FlowRate).GetProperty("CubicMetersPerMinute").GetGetMethod()) },
{ Unit.CubicMetersPerHour, new UnitInfo<FlowRate>(UnitAbbreviations[Unit.CubicMetersPerHour], FromCubicMetersPerHour, typeof(FlowRate).GetProperty("CubicMetersPerHour").GetGetMethod()) },
{ Unit.GallonsPerMinute, new UnitInfo<FlowRate>(UnitAbbreviations[Unit.GallonsPerMinute], FromGallonsPerMinute, typeof(FlowRate).GetProperty("GallonsPerMinute").GetGetMethod()) }
};
/// <summary>
/// Prevents a default instance of the <see cref="FlowRate"/> class from being created
/// Use FromXXX methods to create objects of this type.
/// </summary>
private FlowRate()
{
throw new InvalidOperationException("No one should be calling this, it is only here to prevent users from creating default object");
}
/// <summary>
/// Constructor used by this class to create objects in FromXXX methods.
/// </summary>
/// <param name="flowRate">The flow rate - Cubic Meters per second</param>
private FlowRate(double cubicMetersPerSecond)
{
_flowRate = cubicMetersPerSecond;
}
#region conversion properties
/// <summary>
/// Returns Cubic Meters Per Second as type double
/// </summary>
public double CubicMetersPerSecond { get { return _flowRate; } }
/// <summary>
/// Returns Cubic Meters Per Minutes as type double
/// </summary>
public double CubicMetersPerMinute { get { return _flowRate * SecondsPerMinute; } }
/// <summary>
/// Returns Cubic Meters Per Hour as type double
/// </summary>
public double CubicMetersPerHour { get { return _flowRate * SecondsPerHour; } }
/// <summary>
/// Returns Gallons Per Minute
/// </summary>
public double GallonsPerMinute { get { return _flowRate * CubicMetersToGalPerSecMultipler; } }
#endregion
#region Creation Methods
/// <summary>
/// Returns FlowRate object interpreting passed value as Cubic Meters Per Second
/// </summary>
/// <param name="flowRate">Cubic Meters Per Second</param>
/// <returns></returns>
public static FlowRate FromCubicMetersPerSecond(double m3PerSec)
{
return new FlowRate(m3PerSec);
}
public static FlowRate FromCubicMetersPerMinute(double m3PerMin)
{
return new FlowRate(m3PerMin / SecondsPerMinute);
}
public static FlowRate FromCubicMetersPerHour(double m3PerHr)
{
return new FlowRate(m3PerHr / SecondsPerHour);
}
public static FlowRate FromGallonsPerMinute(double gallonPerMin)
{
return new FlowRate(gallonPerMin / CubicMetersToGalPerSecMultipler);
}
#endregion
public override bool Equals(object obj)
{
FlowRate flowRate = obj as FlowRate;
return (flowRate == null) ? false : (this._flowRate == flowRate._flowRate);
}
public override int GetHashCode()
{
return _flowRate.GetHashCode();
}
#region Binary Operators
// not implementing %, &, |, ^, <<, >>
public static FlowRate operator +(FlowRate left, FlowRate right)
{
if (null == left)
{
throw new ArgumentNullException("left", "Cannot add a null Flow Rate");
}
if (null == right)
{
throw new ArgumentNullException("right", "Cannot add null Flow Rate");
}
return new FlowRate(left._flowRate + right._flowRate);
}
public static FlowRate operator *(FlowRate flowRate, double scalar)
{
if (null == flowRate)
{
throw new ArgumentNullException("flowRate", "Cannot multiply a null Flow Rate");
}
return new FlowRate(flowRate._flowRate * scalar);
}
public static FlowRate operator *(double scalar, FlowRate flowRate)
{
if (null == flowRate)
{
throw new ArgumentNullException("flowRate", "Cannot multiply a null Flow Rate");
}
return new FlowRate(scalar * flowRate._flowRate);
}
public static FlowRate operator /(FlowRate flowRate, double scalar)
{
if (null == flowRate)
{
throw new ArgumentNullException("flowRate", "Cannot divide a null Flow Rate");
}
if (0.0 == scalar)
{
throw new DivideByZeroException("Cannot divide Flow Rate by 0");
}
return new FlowRate(flowRate._flowRate / scalar);
}
#endregion
#region comparison operators
public static bool operator ==(FlowRate left, FlowRate right)
{
bool bReturn = false;
if (object.ReferenceEquals(left, null))
{
if (object.ReferenceEquals(right, null))
{
//both are null, so we are ==
bReturn = true;
}
}
else
{
if (!object.ReferenceEquals(left, null) &&
!object.ReferenceEquals(right, null))
{
bReturn = left._flowRate == right._flowRate;
}
}
return bReturn;
}
public static bool operator !=(FlowRate left, FlowRate right)
{
return !(left == right);
}
public static bool operator <(FlowRate left, FlowRate right)
{
if (null == left)
{
throw new ArgumentNullException("left", "Cannot compare null Flow Rate");
}
if (null == right)
{
throw new ArgumentNullException("right", "Cannot compare null Flow Rate");
}
return (left._flowRate < right._flowRate);
}
public static bool operator >(FlowRate left, FlowRate right)
{
if (null == left)
{
throw new ArgumentNullException("left", "Cannot compare null Flow Rate");
}
if (null == right)
{
throw new ArgumentNullException("right", "Cannot compare null Flow Rate");
}
return (left._flowRate > right._flowRate);
}
public static bool operator <=(FlowRate left, FlowRate right)
{
if (null == left)
{
throw new ArgumentNullException("left", "Cannot compare null Flow Rate");
}
if (null == right)
{
throw new ArgumentNullException("right", "Cannot compare null Flow Rate");
}
return (left._flowRate <= right._flowRate);
}
public static bool operator >=(FlowRate left, FlowRate right)
{
if (null == left)
{
throw new ArgumentNullException("left", "Cannot compare null Flow Rate");
}
if (null == right)
{
throw new ArgumentNullException("right", "Cannot compare null Flow Rate");
}
return (left._flowRate >= right._flowRate);
}
#endregion
#region parsing
public static FlowRate Parse(string s)
{
return Common.Parse(s, _unitInfo);
}
public static bool TryParse(string s, out FlowRate value)
{
try
{
value = FlowRate.Parse(s);
return true;
}
catch (Exception)
{
value = null;
return false;
}
}
#endregion
/// <summary>
/// Returns a <see cref="string" /> appended with units symbol (e.g. "1.23 M^3/s").
/// </summary>
/// <returns>
/// A <see cref="string" /> that represents this instance.
/// </returns>
public override string ToString()
{
return ToString(DefaultUnits);
}
/// <summary>
/// overload that returns a string appended with specified units (e.g. "1.23 ft/sec^2").
/// </summary>
/// <param name="units"></param>
/// <returns></returns>
public string ToString(Unit units)
{
double value = (double)_unitInfo[units].PropertyGetter.Invoke(this, null);
return $"{value} {_unitInfo[units].Abbreviation[0]}";
}
}
}

View File

@@ -0,0 +1,340 @@
using System;
using System.Collections.Generic;
using System.Runtime.Serialization;
namespace Raytheon.Units
{
/// <summary>
/// This class represents energy.
///
/// It has no constructors. Instead, it provides multiple methods for creating objects of this
/// type. Those methods are of the form FromXXX, where XXX is a unit (e.g. FromHertz).
///
/// Properties (e.g. Hertz) are provided to convert the value to other units and return as type
/// double.
/// </summary>
[Serializable]
[DataContract]
public class Frequency
{
public enum Unit
{
Hertz,
KiloHertz,
MegaHertz,
GigaHertz
}
public static IDictionary<Unit, List<string>> UnitAbbreviations = new Dictionary<Unit, List<string>>()
{
{Unit.Hertz, new List<string>(){ "Hz" } },
{Unit.KiloHertz, new List<string>(){ "kHz" } },
{Unit.MegaHertz, new List<string>(){ "MHz" } },
{Unit.GigaHertz, new List<string>(){ "GHz" } },
};
private const Unit DefaultUnits = Unit.Hertz;
[DataMember(Name = "Frequency", IsRequired = true)]
private double _frequency; // Hertz
// map: unit => abbreviation, conversion method and property
private static IDictionary<Unit, UnitInfo<Frequency>> _unitInfo = new Dictionary<Unit, UnitInfo<Frequency>>()
{
{ Unit.Hertz, new UnitInfo<Frequency>(UnitAbbreviations[Unit.Hertz], FromHertz, typeof(Frequency).GetProperty("Hertz").GetGetMethod()) },
{ Unit.KiloHertz, new UnitInfo<Frequency>(UnitAbbreviations[Unit.KiloHertz], FromKiloHertz, typeof(Frequency).GetProperty("KiloHertz").GetGetMethod()) },
{ Unit.MegaHertz, new UnitInfo<Frequency>(UnitAbbreviations[Unit.MegaHertz], FromMegaHertz, typeof(Frequency).GetProperty("MegaHertz").GetGetMethod()) },
{ Unit.GigaHertz, new UnitInfo<Frequency>(UnitAbbreviations[Unit.GigaHertz], FromGigaHertz, typeof(Frequency).GetProperty("GigaHertz").GetGetMethod()) }
};
/// <summary>
/// Prevents a default instance of the <see cref="Frequency"/> class from being created.
/// Use FromXXX methods to create objects of this type.
/// </summary>
/// <exception cref="System.Exception">No one should be calling this, it is only here to prevent users from creating default object</exception>
private Frequency()
{
throw new InvalidOperationException("No one should be calling this, it is only here to prevent users from creating default object");
}
/// <summary>
/// ctor used by this class to create objects in FromXXX methods
/// </summary>
/// <param name="frequency">The frequency - Hertz.</param>
private Frequency(double frequency)
{
_frequency = frequency;
}
#region conversion properties
public double GigaHertz
{
get { return _frequency / Constants.GIGA; }
}
public double Hertz
{
get { return _frequency; }
}
public double KiloHertz
{
get { return _frequency / Constants.KILO; }
}
public double MegaHertz
{
get { return _frequency / Constants.MEGA; }
}
#endregion
#region creation methods
/// <summary>
/// Returns Frequency object interpreting passed value as Hertz
/// </summary>
/// <param name="frequency">Hertz</param>
/// <returns></returns>
public static Frequency FromGigaHertz(double frequency)
{
return new Frequency(frequency * Constants.GIGA);
}
/// <summary>
/// Returns Frequency object interpreting passed value as Hertz
/// </summary>
/// <param name="frequency">Hertz</param>
/// <returns></returns>
public static Frequency FromHertz(double frequency)
{
return new Frequency(frequency);
}
/// <summary>
/// Returns Frequency object interpreting passed value as Hertz
/// </summary>
/// <param name="frequency">Hertz</param>
/// <returns></returns>
public static Frequency FromKiloHertz(double frequency)
{
return new Frequency(frequency * Constants.KILO);
}
/// <summary>
/// Returns Frequency object interpreting passed value as Hertz
/// </summary>
/// <param name="frequency">Hertz</param>
/// <returns></returns>
public static Frequency FromMegaHertz(double frequency)
{
return new Frequency(frequency * Constants.MEGA);
}
#endregion
public override bool Equals(object obj)
{
Frequency e = obj as Frequency;
return (e == null) ? false : (this._frequency == e._frequency);
}
public override int GetHashCode()
{
return _frequency.GetHashCode();
}
#region binary operators
// not implementing %, &, |, ^, <<, >>
public static Frequency operator +(Frequency left, Frequency right)
{
if (null == left)
throw new ArgumentNullException("left", "Cannot add a null Frequency");
if (null == right)
throw new ArgumentNullException("right", "Cannot add null Frequency");
return new Frequency(left._frequency + right._frequency);
}
public static Frequency operator -(Frequency left, Frequency right)
{
if (null == left)
throw new ArgumentNullException("left", "Cannot subtract a null Frequency");
if (null == right)
throw new ArgumentNullException("right", "Cannot subtract a null Frequency");
return new Frequency(left._frequency - right._frequency);
}
public static Frequency operator *(Frequency frequency, double scalar)
{
if (null == frequency)
throw new ArgumentNullException("frequency", "Cannot multiply a null Frequency");
return new Frequency(frequency._frequency * scalar);
}
public static Frequency operator *(double scalar, Frequency frequency)
{
if (null == frequency)
throw new ArgumentNullException("frequency", "Cannot multiply a null Frequency");
return new Frequency(scalar * frequency._frequency);
}
public static Frequency operator /(Frequency frequency, double scalar)
{
if (null == frequency)
throw new ArgumentNullException("frequency", "Cannot divide a null Frequency");
if (0.0 == scalar)
throw new DivideByZeroException("Cannot divide Frequency by 0");
return new Frequency(frequency._frequency / scalar);
}
#endregion
#region comparison operators
public static bool operator ==(Frequency left, Frequency right)
{
bool bReturn = false;
if (object.ReferenceEquals(left, null))
{
if (object.ReferenceEquals(right, null))
{
//both are null, so we are ==
bReturn = true;
}
}
else
{
if (!object.ReferenceEquals(left, null) &&
!object.ReferenceEquals(right, null))
{
bReturn = left._frequency == right._frequency;
}
}
return bReturn;
}
public static bool operator !=(Frequency left, Frequency right)
{
return !(left == right);
}
public static bool operator <(Frequency left, Frequency right)
{
if (null == left)
throw new ArgumentNullException("left", "Cannot compare null Frequency");
if (null == right)
throw new ArgumentNullException("right", "Cannot compare null Frequency");
return (left._frequency < right._frequency);
}
public static bool operator >(Frequency left, Frequency right)
{
if (null == left)
throw new ArgumentNullException("left", "Cannot compare null Frequency");
if (null == right)
throw new ArgumentNullException("right", "Cannot compare null Frequency");
return (left._frequency > right._frequency);
}
public static bool operator <=(Frequency left, Frequency right)
{
if (null == left)
throw new ArgumentNullException("left", "Cannot compare null Frequency");
if (null == right)
throw new ArgumentNullException("right", "Cannot compare null Frequency");
return (left._frequency <= right._frequency);
}
public static bool operator >=(Frequency left, Frequency right)
{
if (null == left)
throw new ArgumentNullException("left", "Cannot compare null Frequency");
if (null == right)
throw new ArgumentNullException("right", "Cannot compare null Frequency");
return (left._frequency >= right._frequency);
}
#endregion
#region operators with other classes
// no operators right now
#endregion
#region parsing
public static Frequency Parse(string s)
{
return Common.Parse(s, _unitInfo);
}
public static bool TryParse(string s, out Frequency value)
{
try
{
value = Frequency.Parse(s);
return true;
}
catch (Exception)
{
value = null;
return false;
}
}
#endregion
/// <summary>
/// Returns a string appended with default units (e.g. "1.23 m/sec^2").
/// </summary>
/// <returns>
/// A string that represents this instance
/// </returns>
public override string ToString()
{
return ToString(DefaultUnits);
}
/// <summary>
/// overload that returns a string appended with specified units (e.g. "1.23 ft/sec^2").
/// </summary>
/// <param name="units"></param>
/// <returns></returns>
public string ToString(Unit units)
{
double value = (double)_unitInfo[units].PropertyGetter.Invoke(this, null);
return $"{value} {_unitInfo[units].Abbreviation[0]}";
}
}
}

View File

@@ -0,0 +1,412 @@
using System;
using System.Text;
using System.Runtime.Serialization;
using System.Diagnostics.CodeAnalysis;
using System.Collections.Generic;
namespace Raytheon.Units
{
/// <summary>
/// This class represents a length.
///
/// It has no constructors. Instead, it provides multiple methods for creating objects of this
/// type. Those methods are of the form FromXXX, where XXX is a unit (e.g. FromMeters).
///
/// Properties (e.g. Meters) are provided to convert the value to other units and return
/// as type double.
///
/// Methods (operator overloads) are provided to perform calculations with related types (e.g.
/// Velocity).
/// </summary>
[Serializable]
[DataContract]
public class Length
{
public enum Unit
{
Meters,
Centimeters,
Millimeters,
Micrometers,
Nanometers,
Inches,
Feet
}
public static IDictionary<Unit, List<string>> UnitAbbreviations = new Dictionary<Unit, List<string>>()
{
{Unit.Meters, new List<string>(){ "m" } },
{Unit.Centimeters, new List<string>(){ "cm" } },
{Unit.Millimeters, new List<string>(){ "mm" } },
{Unit.Micrometers, new List<string>(){ "um" } },
{Unit.Nanometers, new List<string>(){ "nm" } },
{Unit.Inches, new List<string>(){ "in" } },
{Unit.Feet, new List<string>(){ "ft" } },
};
private const Unit DefaultUnits = Unit.Meters;
private const double FeetPerMeter = 3.280839895013123;
private const double InchesPerMeter = 12 * FeetPerMeter;
private const double MilesPerMeter = FeetPerMeter / 5280;
[DataMember(Name = "Length", IsRequired = true)]
private double _length; // meters
// map: unit => abbreviation, conversion method and property
private static IDictionary<Unit, UnitInfo<Length>> _unitInfo = new Dictionary<Unit, UnitInfo<Length>>()
{
{ Unit.Meters, new UnitInfo<Length>(UnitAbbreviations[Unit.Meters], FromMeters, typeof(Length).GetProperty("Meters").GetGetMethod()) },
{ Unit.Centimeters, new UnitInfo<Length>(UnitAbbreviations[Unit.Centimeters], FromCentimeters, typeof(Length).GetProperty("Centimeters").GetGetMethod()) },
{ Unit.Millimeters, new UnitInfo<Length>(UnitAbbreviations[Unit.Millimeters], FromMillimeters, typeof(Length).GetProperty("Millimeters").GetGetMethod()) },
{ Unit.Micrometers, new UnitInfo<Length>(UnitAbbreviations[Unit.Micrometers], FromMicrometers, typeof(Length).GetProperty("Micrometers").GetGetMethod()) },
{ Unit.Nanometers, new UnitInfo<Length>(UnitAbbreviations[Unit.Nanometers], FromNanometers, typeof(Length).GetProperty("Nanometers").GetGetMethod()) },
{ Unit.Feet, new UnitInfo<Length>(UnitAbbreviations[Unit.Feet], FromFeet, typeof(Length).GetProperty("Feet").GetGetMethod()) },
{ Unit.Inches, new UnitInfo<Length>(UnitAbbreviations[Unit.Inches], FromInches, typeof(Length).GetProperty("Inches").GetGetMethod()) }
};
/// <summary>
/// Prevents a default instance of the <see cref="Length"/> class from being created.
/// Use FromXXX methods to create objects of this type.
/// </summary>
/// <exception cref="System.Exception">No one should be calling this, it is only here to prevent users from creating default object</exception>
private Length()
{
throw new InvalidOperationException("No one should be calling this, it is only here to prevent users from creating default object");
}
/// <summary>
/// ctor used by this class to create objects in FromXXX methods
/// </summary>
/// <param name="length">The length - meters</param>
private Length(double length)
{
_length = length;
}
#region conversion properties
public double Centimeters
{
get { return _length * 100; }
}
public double Feet
{
get { return _length * FeetPerMeter; }
}
public double Inches
{
get { return _length * InchesPerMeter; }
}
public double Meters
{
get { return _length; }
}
public double Micrometers
{
get { return _length * 1000000; }
}
public double Millimeters
{
get { return _length * 1000; }
}
public double Nanometers
{
get { return _length * 1000000000; }
}
#endregion
#region creation methods
public static Length FromCentimeters(double centimeters)
{
return new Length(centimeters / 100);
}
public static Length FromFeet(double feet)
{
return new Length(feet / FeetPerMeter);
}
public static Length FromInches(double inches)
{
return new Length(inches / InchesPerMeter);
}
public static Length FromMeters(double meters)
{
return new Length(meters);
}
public static Length FromMicrometers(double micrometers)
{
return new Length(micrometers / 1000000);
}
public static Length FromMillimeters(double millimeters)
{
return new Length(millimeters / 1000);
}
public static Length FromNanometers(double nanometers)
{
return new Length(nanometers / 1000000000);
}
#endregion
public override bool Equals(object obj)
{
Length l = obj as Length;
return (l == null) ? false : (this._length == l._length);
}
public override int GetHashCode()
{
return _length.GetHashCode();
}
#region binary operators
// not implementing %, &, |, ^, <<, >>
public static Length operator +(Length left, Length right)
{
if (null == left)
throw new ArgumentNullException("left", "Cannot add a null Length");
if (null == right)
throw new ArgumentNullException("right", "Cannot add null Length");
return new Length(left._length + right._length);
}
public static Length operator -(Length left, Length right)
{
if (null == left)
throw new ArgumentNullException("left", "Cannot subtract a null Length");
if (null == right)
throw new ArgumentNullException("right", "Cannot subtract a null Length");
return new Length(left._length - right._length);
}
public static Length operator *(Length length, double scalar)
{
if (null == length)
throw new ArgumentNullException("length", "Cannot multiply a null Length");
return new Length(length._length * scalar);
}
public static Length operator *(double scalar, Length length)
{
if (null == length)
throw new ArgumentNullException("length", "Cannot multiply a null Length");
return new Length(scalar * length._length);
}
public static Length operator /(Length length, double scalar)
{
if (null == length)
throw new ArgumentNullException("length", "Cannot divide a null Length");
if (0.0 == scalar)
throw new DivideByZeroException("Cannot divide Length by 0");
return new Length(length._length / scalar);
}
#endregion
#region comparison operators
public static bool operator ==(Length left, Length right)
{
bool bReturn = false;
if (object.ReferenceEquals(left, null))
{
if (object.ReferenceEquals(right, null))
{
//both are null, so we are ==
bReturn = true;
}
}
else
{
if (!object.ReferenceEquals(left, null) &&
!object.ReferenceEquals(right, null))
{
bReturn = left._length == right._length;
}
}
return bReturn;
}
public static bool operator !=(Length left, Length right)
{
return !(left == right);
}
public static bool operator <(Length left, Length right)
{
if (null == left)
throw new ArgumentNullException("left", "Cannot compare null Length");
if (null == right)
throw new ArgumentNullException("right", "Cannot compare null Length");
return (left._length < right._length);
}
public static bool operator >(Length left, Length right)
{
if (null == left)
throw new ArgumentNullException("left", "Cannot compare null Length");
if (null == right)
throw new ArgumentNullException("right", "Cannot compare null Length");
return (left._length > right._length);
}
public static bool operator <=(Length left, Length right)
{
if (null == left)
throw new ArgumentNullException("left", "Cannot compare null Length");
if (null == right)
throw new ArgumentNullException("right", "Cannot compare null Length");
return (left._length <= right._length);
}
public static bool operator >=(Length left, Length right)
{
if (null == left)
throw new ArgumentNullException("left", "Cannot compare null Length");
if (null == right)
throw new ArgumentNullException("right", "Cannot compare null Length");
return (left._length >= right._length);
}
#endregion
#region operators with non-length classes
/// <summary>
/// Implements the operator / for Velocity = Length / PrecisionTimeSpan
/// </summary>
/// <param name="length">The length.</param>
/// <param name="time">The time.</param>
/// <returns>
/// Velocity
/// </returns>
public static Velocity operator /(Length length, PrecisionTimeSpan time)
//public static Velocity operator /(Length length, TimeSpan time)
{
if (null == length)
throw new ArgumentNullException("length", "Cannot divide a null Length");
if (null == time)
throw new ArgumentNullException("time", "Cannot divide by a null PrecisionTimeSpan");
if (0.0 == time.Milliseconds)
throw new DivideByZeroException("Cannot divide Length by 0 time");
return Velocity.FromMetersPerSec(length.Meters / time.Seconds);
}
/// <summary>
/// Implements the operator / for PrecisionTimeSpan = Length / Velocity
/// </summary>
/// <param name="length">The length.</param>
/// <param name="time">The velocity.</param>
/// <returns>
/// PrecisionTimeSpan
/// </returns>
public static PrecisionTimeSpan operator /(Length length, Velocity velocity)
{
if (null == length)
throw new ArgumentNullException("length", "Cannot divide a null Length");
if (null == velocity)
throw new ArgumentNullException("velocity", "Cannot divide by a null Velocity");
if (0.0 == velocity.MetersPerSec)
throw new DivideByZeroException("Cannot divide Length by 0 velocity");
return PrecisionTimeSpan.FromSeconds(length.Meters / velocity.MetersPerSec);
}
#endregion
#region parsing
public static Length Parse(string s)
{
return Common.Parse(s, _unitInfo);
}
public static bool TryParse(string s, out Length value)
{
try
{
value = Length.Parse(s);
return true;
}
catch (Exception)
{
value = null;
return false;
}
}
#endregion
/// <summary>
/// Returns a string appended with default units (e.g. "1.23 m/sec^2").
/// </summary>
/// <returns>
/// A string that represents this instance
/// </returns>
public override string ToString()
{
return ToString(DefaultUnits);
}
/// <summary>
/// overload that returns a string appended with specified units (e.g. "1.23 ft/sec^2").
/// </summary>
/// <param name="units"></param>
/// <returns></returns>
public string ToString(Unit units)
{
double value = (double)_unitInfo[units].PropertyGetter.Invoke(this, null);
return $"{value} {_unitInfo[units].Abbreviation[0]}";
}
}
}

View File

@@ -0,0 +1,333 @@
using System;
using System.Text;
using System.Runtime.Serialization;
using System.Diagnostics.CodeAnalysis;
using System.Collections.Generic;
namespace Raytheon.Units
{
/// <summary>
/// This class represents energy.
///
/// It has no constructors. Instead, it provides multiple methods for creating objects of this
/// type. Those methods are of the form FromXXX, where XXX is a unit (e.g. FromWatts).
///
/// Properties (e.g. Watts) are provided to convert the value to other units and return
/// as type double.
/// </summary>
[Serializable]
[DataContract]
public class Power
{
public enum Unit
{
Watts,
Milliwatts,
DecibelMilliWatt
}
public static IDictionary<Unit, List<string>> UnitAbbreviations = new Dictionary<Unit, List<string>>()
{
{Unit.Watts, new List<string>(){ "W", "Watts", "Watt" } },
{Unit.Milliwatts, new List<string>(){ "mW", "MilliWatt", "MilliWatts" } },
{Unit.DecibelMilliWatt, new List<string>(){ "dBm", "DecibelMilliWatt", "DecibelMilliWatts" } }
};
private const Unit DefaultUnits = Unit.Watts;
[DataMember(Name = "Power", IsRequired = true)]
private readonly double _power; // watts
// map: unit => abbreviation, conversion method and property
private static readonly IDictionary<Unit, UnitInfo<Power>> _unitInfo = new Dictionary<Unit, UnitInfo<Power>>()
{
{ Unit.Watts, new UnitInfo<Power>(UnitAbbreviations[Unit.Watts], FromWatts, typeof(Power).GetProperty("Watts").GetGetMethod()) },
{ Unit.Milliwatts, new UnitInfo<Power>(UnitAbbreviations[Unit.Milliwatts], FromMilliwatts, typeof(Power).GetProperty("Milliwatts").GetGetMethod()) },
{ Unit.DecibelMilliWatt, new UnitInfo<Power>(UnitAbbreviations[Unit.DecibelMilliWatt], FromDBM, typeof(Power).GetProperty("DBM").GetGetMethod()) }
};
/// <summary>
/// Prevents a default instance of the <see cref="Power"/> class from being created.
/// Use FromXXX methods to create objects of this type.
/// </summary>
/// <exception cref="System.Exception">No one should be calling this, it is only here to prevent users from creating default object</exception>
private Power()
{
throw new InvalidOperationException("No one should be calling this, it is only here to prevent users from creating default object");
}
/// <summary>
/// ctor used by this class to create objects in FromXXX methods
/// </summary>
/// <param name="energy">The energy - watts/cm^2.</param>
private Power(double energy)
{
_power = energy;
}
#region conversion properties
public double Milliwatts
{
get { return _power * 1000; }
}
public double Watts
{
get { return _power; }
}
public double DBM
{
get { return (10 * Math.Log10(Math.Abs(_power))) + 30; }
}
/// <summary>
/// Returns watts/cm^2 as type double
/// </summary>
/// <value>
/// watts/cm^2
/// </value>
[Obsolete("WattsPerCmSqrd is deprecated, please use Watts instead. This will be removed in a future version.", false)]
public double WattsPerCmSqrd
{
get
{
return Double.NaN;
}
}
#endregion
#region creation methods
/// </summary>
/// <param name="wattsPerCmSqrd">watts/cm^2</param>
/// <returns></returns>
[Obsolete("FromWattsPerCmSqrd is deprecated, please use FromWatts instead. This will be removed in a future version.", false)]
public static Power FromWattsPerCmSqrd(double wattsPerCmSqrd)
{
return new Power(Double.NaN);
}
/// <summary>
/// Returns Power object interpreting passed value as milliwatts
/// </summary>
/// <param name="milliwatts">milliwatts</param>
/// <returns></returns>
public static Power FromMilliwatts(double milliwatts)
{
return new Power(milliwatts / 1000);
}
/// <summary>
/// Returns Power object interpreting passed value as watts
/// </summary>
/// <param name="watts">watts</param>
/// <returns></returns>
public static Power FromWatts(double watts)
{
return new Power(watts);
}
public static Power FromDBM(double dbm)
{
return new Power(Math.Pow(10, (dbm - 30) / 10));
}
#endregion
public override bool Equals(object obj)
{
Power e = obj as Power;
return (e == null) ? false : (this._power == e._power);
}
public override int GetHashCode()
{
return _power.GetHashCode();
}
#region binary operators
// not implementing %, &, |, ^, <<, >>
public static Power operator +(Power left, Power right)
{
if (null == left)
throw new ArgumentNullException("left", "Cannot add a null Power");
if (null == right)
throw new ArgumentNullException("right", "Cannot add null Power");
return new Power(left._power + right._power);
}
public static Power operator -(Power left, Power right)
{
if (null == left)
throw new ArgumentNullException("left", "Cannot subtract a null Power");
if (null == right)
throw new ArgumentNullException("right", "Cannot subtract a null Power");
return new Power(left._power - right._power);
}
public static Power operator *(Power power, double scalar)
{
if (null == power)
throw new ArgumentNullException("power", "Cannot multiply a null Power");
return new Power(power._power * scalar);
}
public static Power operator *(double scalar, Power power)
{
if (null == power)
throw new ArgumentNullException("power", "Cannot multiply a null Power");
return new Power(scalar * power._power);
}
public static Power operator /(Power power, double scalar)
{
if (null == power)
throw new ArgumentNullException("power", "Cannot divide a null Power");
if (0.0 == scalar)
throw new DivideByZeroException("Cannot divide Power by 0");
return new Power(power._power / scalar);
}
#endregion
#region comparison operators
public static bool operator ==(Power left, Power right)
{
bool bReturn = false;
if (object.ReferenceEquals(left, null))
{
if (object.ReferenceEquals(right, null))
{
//both are null, so we are ==
bReturn = true;
}
}
else
{
if (!object.ReferenceEquals(left, null) &&
!object.ReferenceEquals(right, null))
{
bReturn = left._power == right._power;
}
}
return bReturn;
}
public static bool operator !=(Power left, Power right)
{
return !(left == right);
}
public static bool operator <(Power left, Power right)
{
if (null == left)
throw new ArgumentNullException("left", "Cannot compare null Power");
if (null == right)
throw new ArgumentNullException("right", "Cannot compare null Power");
return (left._power < right._power);
}
public static bool operator >(Power left, Power right)
{
if (null == left)
throw new ArgumentNullException("left", "Cannot compare null Power");
if (null == right)
throw new ArgumentNullException("right", "Cannot compare null Power");
return (left._power > right._power);
}
public static bool operator <=(Power left, Power right)
{
if (null == left)
throw new ArgumentNullException("left", "Cannot compare null Power");
if (null == right)
throw new ArgumentNullException("right", "Cannot compare null Power");
return (left._power <= right._power);
}
public static bool operator >=(Power left, Power right)
{
if (null == left)
throw new ArgumentNullException("left", "Cannot compare null Power");
if (null == right)
throw new ArgumentNullException("right", "Cannot compare null Power");
return (left._power >= right._power);
}
#endregion
#region operators with other classes
// no operators right now
#endregion
#region parsing
public static Power Parse(string s)
{
return Common.Parse(s, _unitInfo);
}
public static bool TryParse(string s, out Power value)
{
try
{
value = Power.Parse(s);
return true;
}
catch (Exception)
{
value = null;
return false;
}
}
#endregion
/// <summary>
/// Returns a string appended with default units (e.g. "1.23 m/sec^2").
/// </summary>
/// <returns>
/// A string that represents this instance
/// </returns>
public override string ToString()
{
return ToString(DefaultUnits);
}
/// <summary>
/// overload that returns a string appended with specified units (e.g. "1.23 ft/sec^2").
/// </summary>
/// <param name="units"></param>
/// <returns></returns>
public string ToString(Unit units)
{
double value = (double)_unitInfo[units].PropertyGetter.Invoke(this, null);
return $"{value} {_unitInfo[units].Abbreviation[0]}";
}
}
}

View File

@@ -0,0 +1,357 @@
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Runtime.Serialization;
using System.Text;
namespace Raytheon.Units
{
/// <summary>
/// This class represents precision time spans where the .NET TimeSpan class just does
/// not cut the mustard
///
/// It has no constructors. Instead, it provides multiple methods for creating objects of this
/// type. Those methods are of the form FromXXX, where XXX is a unit (e.g. FromSeconds).
///
/// Properties (e.g. Seconds) are provided to convert the value to other units and return
/// as type double.
///
/// Methods (operator overloads) are provided to perform calculations with related types
/// </summary>
[Serializable]
[DataContract]
public class PrecisionTimeSpan
{
public enum Unit
{
Seconds,
Milliseconds,
Microseconds,
Nanoseconds
}
public static IDictionary<Unit, List<string>> UnitAbbreviations = new Dictionary<Unit, List<string>>()
{
{Unit.Seconds, new List<string>(){ "sec" } },
{Unit.Milliseconds, new List<string>(){ "msec" } },
{Unit.Microseconds, new List<string>(){ "usec" } },
{Unit.Nanoseconds, new List<string>(){ "nsec" } },
};
private const Unit DefaultUnits = Unit.Seconds;
[DataMember(Name = "BaseTimeSpan", IsRequired = true)]
private Decimal _totalns; //base will be nano seconds... max will be double.MaxValue
//min will be 0
// map: unit => abbreviation, conversion method and property
private static IDictionary<Unit, UnitInfo<PrecisionTimeSpan>> _unitInfo = new Dictionary<Unit, UnitInfo<PrecisionTimeSpan>>()
{
{ Unit.Seconds, new UnitInfo<PrecisionTimeSpan>(UnitAbbreviations[Unit.Seconds], FromSeconds, typeof(PrecisionTimeSpan).GetProperty("Seconds").GetGetMethod()) },
{ Unit.Milliseconds, new UnitInfo<PrecisionTimeSpan>(UnitAbbreviations[Unit.Milliseconds], FromMilliseconds, typeof(PrecisionTimeSpan).GetProperty("Milliseconds").GetGetMethod()) },
{ Unit.Microseconds, new UnitInfo<PrecisionTimeSpan>(UnitAbbreviations[Unit.Microseconds], FromMicroseconds, typeof(PrecisionTimeSpan).GetProperty("Microseconds").GetGetMethod()) },
{ Unit.Nanoseconds, new UnitInfo<PrecisionTimeSpan>(UnitAbbreviations[Unit.Nanoseconds], FromNanoseconds, typeof(PrecisionTimeSpan).GetProperty("Nanoseconds").GetGetMethod()) }
};
internal const Decimal _nanoPerMicro = 1e3M;
internal const Decimal _nanoPerMilli = 1e6M;
internal const Decimal _nanoPerSec = 1e9M;
/// <summary>
/// Prevents a default instance of the <see cref="PrecisionTimeSpan"/> class from being created.
/// Use FromXXX methods to create objects of this type.
/// </summary>
/// <exception cref="System.Exception">No one should be calling this, it is only here to prevent users from creating default object</exception>
private PrecisionTimeSpan()
{
throw new InvalidOperationException("No one should be calling this, it is only here to prevent users from creating default object");
}
/// <summary>
/// ctor used by this class to create objects in FromXXX methods
/// </summary>
/// <param name="totalns">total number of nanoseconds.</param>
private PrecisionTimeSpan(Decimal totalns)
{
if (totalns < 0.0M)
throw new ArgumentOutOfRangeException("totalns", "Cannot create a negative timespan");
_totalns = totalns;
}
#region conversion properties
public double Nanoseconds
{
get { return (double)_totalns; }
}
public double Microseconds
{
get { return (double)(_totalns / _nanoPerMicro); }
}
public double Milliseconds
{
get { return (double)(_totalns / _nanoPerMilli); }
}
public double Seconds
{
get { return (double)(_totalns / _nanoPerSec); }
}
#endregion
#region creation methods
/// <summary>
/// Returns PrecisionTimeSpan object interpreting passed value as nanoseconds
/// </summary>
/// <param name="nanoseconds">total nanoseconds in the desired timespan</param>
/// <returns>the precision time span object</returns>
public static PrecisionTimeSpan FromNanoseconds(double nanoseconds)
{
return new PrecisionTimeSpan((Decimal)nanoseconds);
}
/// <summary>
/// Returns PrecisionTimeSpan object interpreting passed value as microseconds
/// </summary>
/// <param name="nanoseconds">total microseconds in the desired timespan</param>
/// <returns>the precision time span object</returns>
public static PrecisionTimeSpan FromMicroseconds(double microseconds)
{
return new PrecisionTimeSpan((Decimal)microseconds * _nanoPerMicro);
}
/// <summary>
/// Returns PrecisionTimeSpan object interpreting passed value as milliseconds
/// </summary>
/// <param name="nanoseconds">total milliseconds in the desired timespan</param>
/// <returns>the precision time span object</returns>
public static PrecisionTimeSpan FromMilliseconds(double milliseconds)
{
return new PrecisionTimeSpan((Decimal)milliseconds * _nanoPerMilli);
}
/// <summary>
/// Returns PrecisionTimeSpan object interpreting passed value as seconds
/// </summary>
/// <param name="nanoseconds">total seconds in the desired timespan</param>
/// <returns>the precision time span object</returns>
public static PrecisionTimeSpan FromSeconds(double seconds)
{
return new PrecisionTimeSpan((Decimal)seconds * _nanoPerSec);
}
#endregion
public override bool Equals(object obj)
{
PrecisionTimeSpan ts = obj as PrecisionTimeSpan;
return (ts == null) ? false : (this._totalns == ts._totalns);
}
public override int GetHashCode()
{
return _totalns.GetHashCode();
}
#region binary operators
// not implementing %, &, |, ^, <<, >>
public static PrecisionTimeSpan operator +(PrecisionTimeSpan left, PrecisionTimeSpan right)
{
if (null == left)
throw new ArgumentNullException("left", "Cannot add a null PrecisionTimeSpan");
if (null == right)
throw new ArgumentNullException("right", "Cannot add null PrecisionTimeSpan");
return new PrecisionTimeSpan(left._totalns + right._totalns);
}
public static PrecisionTimeSpan operator -(PrecisionTimeSpan left, PrecisionTimeSpan right)
{
if (null == left)
throw new ArgumentNullException("left", "Cannot subtract a null PrecisionTimeSpan");
if (null == right)
throw new ArgumentNullException("right", "Cannot subtract a null PrecisionTimeSpan");
if (right > left)
throw new ArgumentOutOfRangeException("right", "Cannot subtract a larger span from a smaller one");
return new PrecisionTimeSpan(left._totalns - right._totalns);
}
public static PrecisionTimeSpan operator *(PrecisionTimeSpan precisionTimeSpan, double scalar)
{
if (null == precisionTimeSpan)
throw new ArgumentNullException("precisionTimeSpan", "Cannot multiply a null PrecisionTimeSpan");
return new PrecisionTimeSpan(precisionTimeSpan._totalns * (Decimal)scalar);
}
public static PrecisionTimeSpan operator *(double scalar, PrecisionTimeSpan precisionTimeSpan)
{
if (null == precisionTimeSpan)
throw new ArgumentNullException("precisionTimeSpan", "Cannot multiply a null PrecisionTimeSpan");
return new PrecisionTimeSpan((Decimal)scalar * precisionTimeSpan._totalns);
}
public static PrecisionTimeSpan operator /(PrecisionTimeSpan precisionTimeSpan, double scalar)
{
if (null == precisionTimeSpan)
throw new ArgumentNullException("precisionTimeSpan", "Cannot divide a null PrecisionTimeSpan");
if (0.0 == scalar)
throw new DivideByZeroException("Cannot divide Precision Time Span by 0");
return new PrecisionTimeSpan(precisionTimeSpan._totalns / (Decimal)scalar);
}
#endregion
#region comparison operators
public static bool operator ==(PrecisionTimeSpan left, PrecisionTimeSpan right)
{
bool bReturn = false;
if (object.ReferenceEquals(left, null))
{
if (object.ReferenceEquals(right, null))
{
//both are null, so we are ==
bReturn = true;
}
}
else
{
if (!object.ReferenceEquals(left, null) &&
!object.ReferenceEquals(right, null))
{
bReturn = left._totalns == right._totalns;
}
}
return bReturn;
}
public static bool operator !=(PrecisionTimeSpan left, PrecisionTimeSpan right)
{
return !(left == right);
}
public static bool operator <(PrecisionTimeSpan left, PrecisionTimeSpan right)
{
if (null == left)
throw new ArgumentNullException("left", "Cannot compare null PrecisionTimeSpan");
if (null == right)
throw new ArgumentNullException("right", "Cannot compare null PrecisionTimeSpan");
return (left._totalns < right._totalns);
}
public static bool operator >(PrecisionTimeSpan left, PrecisionTimeSpan right)
{
if (null == left)
throw new ArgumentNullException("left", "Cannot compare null PrecisionTimeSpan");
if (null == right)
throw new ArgumentNullException("right", "Cannot compare null PrecisionTimeSpan");
return (left._totalns > right._totalns);
}
public static bool operator <=(PrecisionTimeSpan left, PrecisionTimeSpan right)
{
if (null == left)
throw new ArgumentNullException("left", "Cannot compare null PrecisionTimeSpan");
if (null == right)
throw new ArgumentNullException("right", "Cannot compare null PrecisionTimeSpan");
return (left._totalns <= right._totalns);
}
public static bool operator >=(PrecisionTimeSpan left, PrecisionTimeSpan right)
{
if (null == left)
throw new ArgumentNullException("left", "Cannot compare null PrecisionTimeSpan");
if (null == right)
throw new ArgumentNullException("right", "Cannot compare null PrecisionTimeSpan");
return (left._totalns >= right._totalns);
}
#endregion
#region operators with other classes
// no operators right now
#endregion
#region parsing
public static PrecisionTimeSpan Parse(string s)
{
return Common.Parse(s, _unitInfo);
}
public static bool TryParse(string s, out PrecisionTimeSpan value)
{
try
{
value = PrecisionTimeSpan.Parse(s);
return true;
}
catch (Exception)
{
value = null;
return false;
}
}
#endregion
/// <summary>
/// Returns a string appended with default units (e.g. "1.23 m/sec^2").
/// </summary>
/// <returns>
/// A string that represents this instance
/// </returns>
public override string ToString()
{
return ToString(DefaultUnits);
}
/// <summary>
/// overload that returns a string appended with specified units (e.g. "1.23 ft/sec^2").
/// </summary>
/// <param name="units"></param>
/// <returns></returns>
public string ToString(Unit units)
{
double value = (double)_unitInfo[units].PropertyGetter.Invoke(this, null);
return $"{value} {_unitInfo[units].Abbreviation[0]}";
}
}
}

View File

@@ -0,0 +1,367 @@
//############################################################################//
// RAYTHEON PROPRIETARY: THIS DOCUMENT CONTAINS DATA OR INFORMATION
// PROPRIETARY TO RAYTHEON COMPANY AND IS RESTRICTED TO USE ONLY BY PERSONS
// AUTHORIZED BY RAYTHEON COMPANY IN WRITING TO USE IT. DISCLOSURE TO
// UNAUTHORIZED PERSONS WOULD LIKELY CAUSE SUBSTANTIAL COMPETITIVE HARM TO
// RAYTHEON COMPANY'S BUSINESS POSITION. NEITHER SAID DOCUMENT NOR ITS
// CONTENTS SHALL BE FURNISHED OR DISCLOSED TO OR COPIED OR USED BY PERSONS
// OUTSIDE RAYTHEON COMPANY WITHOUT THE EXPRESS WRITTEN APPROVAL OF RAYTHEON
// COMPANY.
//
// THIS PROPRIETARY NOTICE IS NOT APPLICABLE IF DELIVERED TO THE U.S. GOVERNMENT
//
// UNPUBLISHED WORK - COPYRIGHT RAYTHEON COMPANY.
//
// WARNING: THIS DOCUMENT CONTAINS TECHNICAL DATA AND / OR TECHNOLOGY WHOSE
// EXPORT OR DISCLOSURE TO NON-U.S. PERSONS, WHEREVER LOCATED, IS RESTRICTED
// BY THE INTERNATIONAL TRAFFIC IN ARMS REGULATIONS (ITAR) (22 C.F.R. SECTION
// 120-130) OR THE EXPORT ADMINISTRATION REGULATIONS (EAR) (15 C.F.R. SECTION
// 730-774). THIS DOCUMENT CANNOT BE EXPORTED (E.G., PROVIDED TO A SUPPLIER
// OUTSIDE OF THE UNITED STATES) OR DISCLOSED TO A NON-U.S. PERSON, WHEREVER
// LOCATED, UNTIL A FINAL JURISDICTION AND CLASSIFICATION DETERMINATION HAS
// BEEN COMPLETED AND APPROVED BY RAYTHEON, AND ANY REQUIRED U.S. GOVERNMENT
// APPROVALS HAVE BEEN OBTAINED. VIOLATIONS ARE SUBJECT TO SEVERE CRIMINAL
// PENALTIES.
//
// DOD 5220.22-M, INDUSTRIAL SECURITY MANUAL, CHAPTER 5, SECTION 1 THROUGH 9 :
// FOR CLASSIFIED DOCUMENTS FOLLOW THE PROCEDURES IN OR DOD 5200.1-R,
// INFORMATION SECURITY PROGRAM, CHAPTER 6. FOR UNCLASSIFIED, LIMITED DOCUMENTS
// DESTROY BY ANY METHOD THAT WILL PREVENT DISCLOSURE OF CONTENTS OR
// RECONSTRUCTION OF THE DOCUMENT.
//############################################################################//
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Runtime.Serialization;
namespace Raytheon.Units
{
/// <summary>
/// This class represents a Pressure
///
/// It has no constructors. Instead, it provides multiple methods for creating objects of this
/// type. Those methods are of the form FromXXX, where XXX is a unit (e.g. Pascal).
///
/// Properties (e.g. Pascal) are provided to convert the value to other units and return
/// as type double.
/// </summary>
[Serializable]
[DataContract]
public class Pressure
{
public enum Unit
{
Bar,
Millibar,
Pascal,
PSI
}
public static IDictionary<Unit, List<string>> UnitAbbreviations = new Dictionary<Unit, List<string>>()
{
{Unit.Bar, new List<string>(){ "bar" } },
{Unit.Millibar, new List<string>(){ "mbar" } },
{Unit.Pascal, new List<string>(){ "Pa" } },
{Unit.PSI, new List<string>(){ "PSI" } },
};
private const Unit DefaultUnits = Unit.PSI;
private const int PascalPerBar = 100000;
private const double PascalPerPSI = 6894.75729;
[DataMember(Name = "Pascal", IsRequired = true)]
private double _pressure; // Pascal
// map: unit => abbreviation, conversion method and property
private static IDictionary<Unit, UnitInfo<Pressure>> _unitInfo = new Dictionary<Unit, UnitInfo<Pressure>>()
{
{ Unit.Bar, new UnitInfo<Pressure>(UnitAbbreviations[Unit.Bar], FromBar, typeof(Pressure).GetProperty("Bar").GetGetMethod()) },
{ Unit.Millibar, new UnitInfo<Pressure>(UnitAbbreviations[Unit.Millibar], FromMillibar, typeof(Pressure).GetProperty("Millibar").GetGetMethod()) },
{ Unit.Pascal, new UnitInfo<Pressure>(UnitAbbreviations[Unit.Pascal], FromPascal, typeof(Pressure).GetProperty("Pascal").GetGetMethod()) },
{ Unit.PSI, new UnitInfo<Pressure>(UnitAbbreviations[Unit.PSI], FromPSI, typeof(Pressure).GetProperty("PSI").GetGetMethod()) }
};
/// <summary>
/// Prevents a default instance of the <see cref="Pressure"/> class from being created
/// Use FromXXX methods to create objects of this type.
/// </summary>
private Pressure()
{
throw new InvalidOperationException("No one should be calling this, it is only here to prevent users from creating default object");
}
/// <summary>
/// ctor used by this class to create objects in FromXXX methods.
/// </summary>
/// <param name="pressure">The pressure - pascal</param>
private Pressure(double pressure)
{
this._pressure = pressure;
}
#region conversion properties
public double Bar { get { return _pressure / PascalPerBar; } }
public double Millibar { get { return _pressure / PascalPerBar * 1000; } }
public double Pascal { get { return _pressure; } }
public double PSI { get { return _pressure / PascalPerPSI; } }
#endregion
#region Creation Methods
public static Pressure FromBar(double bars)
{
return new Pressure(bars * PascalPerBar);
}
public static Pressure FromMillibar(double millibars)
{
return new Pressure(millibars * PascalPerBar / 1000);
}
/// <summary>
/// Returns Pressure object interpreting passed value as Pascal
/// </summary>
/// <param name="Pressure">Pascal</param>
/// <returns></returns>
public static Pressure FromPascal(double pascal)
{
return new Pressure(pascal);
}
public static Pressure FromPSI(double psi)
{
return new Pressure(psi * PascalPerPSI);
}
#endregion
public override bool Equals(object obj)
{
Pressure pressure = obj as Pressure;
return (pressure == null) ? false : (this._pressure == pressure._pressure);
}
public override int GetHashCode()
{
return _pressure.GetHashCode();
}
#region Binary Operators
// not implementing %, &, |, ^, <<, >>
public static Pressure operator +(Pressure left, Pressure right)
{
if (null == left)
{
throw new ArgumentNullException("left", "Cannot add a null Pressure");
}
if (null == right)
{
throw new ArgumentNullException("right", "Cannot add null Pressure");
}
return new Pressure(left._pressure + right._pressure);
}
public static Pressure operator -(Pressure left, Pressure right)
{
if (null == left)
{
throw new ArgumentNullException("left", "Cannot add a null Pressure");
}
if (null == right)
{
throw new ArgumentNullException("right", "Cannot add null Pressure");
}
return new Pressure(left._pressure - right._pressure);
}
public static Pressure operator *(Pressure pressure, double scalar)
{
if (null == pressure)
{
throw new ArgumentNullException("pressure", "Cannot multiply a null Pressure");
}
return new Pressure(pressure._pressure * scalar);
}
public static Pressure operator *(double scalar, Pressure pressure)
{
if (null == pressure)
{
throw new ArgumentNullException("pressure", "Cannot multiply a null Pressure");
}
return new Pressure(scalar * pressure._pressure);
}
public static Pressure operator /(Pressure pressure, double scalar)
{
if (null == pressure)
{
throw new ArgumentNullException("pressure", "Cannot divide a null Pressure");
}
if (0.0 == scalar)
{
throw new DivideByZeroException("Cannot divide Pressure by 0");
}
return new Pressure(pressure._pressure / scalar);
}
#endregion
#region comparison operators
public static bool operator ==(Pressure left, Pressure right)
{
bool bReturn = false;
if (object.ReferenceEquals(left, null))
{
if (object.ReferenceEquals(right, null))
{
//both are null, so we are ==
bReturn = true;
}
}
else
{
if (!object.ReferenceEquals(left, null) &&
!object.ReferenceEquals(right, null))
{
bReturn = left._pressure == right._pressure;
}
}
return bReturn;
}
public static bool operator !=(Pressure left, Pressure right)
{
return !(left == right);
}
public static bool operator <(Pressure left, Pressure right)
{
if (null == left)
{
throw new ArgumentNullException("left", "Cannot compare null Pressure");
}
if (null == right)
{
throw new ArgumentNullException("right", "Cannot compare null Pressure");
}
return (left._pressure < right._pressure);
}
public static bool operator >(Pressure left, Pressure right)
{
if (null == left)
{
throw new ArgumentNullException("left", "Cannot compare null Pressure");
}
if (null == right)
{
throw new ArgumentNullException("right", "Cannot compare null Pressure");
}
return (left._pressure > right._pressure);
}
public static bool operator <=(Pressure left, Pressure right)
{
if (null == left)
{
throw new ArgumentNullException("left", "Cannot compare null Pressure");
}
if (null == right)
{
throw new ArgumentNullException("right", "Cannot compare null Pressure");
}
return (left._pressure <= right._pressure);
}
public static bool operator >=(Pressure left, Pressure right)
{
if (null == left)
{
throw new ArgumentNullException("left", "Cannot compare null Pressure");
}
if (null == right)
{
throw new ArgumentNullException("right", "Cannot compare null Pressure");
}
return (left._pressure >= right._pressure);
}
#endregion
#region parsing
public static Pressure Parse(string s)
{
return Common.Parse(s, _unitInfo);
}
public static bool TryParse(string s, out Pressure value)
{
try
{
value = Pressure.Parse(s);
return true;
}
catch (Exception)
{
value = null;
return false;
}
}
#endregion
/// <summary>
/// Returns a string appended with default units (e.g. "1.23 m/sec^2").
/// </summary>
/// <returns>
/// A string that represents this instance
/// </returns>
public override string ToString()
{
return ToString(DefaultUnits);
}
/// <summary>
/// overload that returns a string appended with specified units (e.g. "1.23 ft/sec^2").
/// </summary>
/// <param name="units"></param>
/// <returns></returns>
public string ToString(Unit units)
{
double value = (double)_unitInfo[units].PropertyGetter.Invoke(this, null);
return $"{value} {_unitInfo[units].Abbreviation[0]}";
}
}
}

View File

@@ -0,0 +1,369 @@
using System;
using System.Text;
using System.Runtime.Serialization;
using System.Diagnostics.CodeAnalysis;
using System.Collections.Generic;
namespace Raytheon.Units
{
/// <summary>
/// This class represents electrical resistance.
///
/// It has no constructors. Instead, it provides multiple methods for creating objects of this
/// type. Those methods are of the form FromXXX, where XXX is a unit (e.g. FromOhms).
///
/// Properties (e.g. KiloOhms) are provided to convert the value to other units and return
/// as type double.
///
/// Methods (operator overloads) are provided to perform calculations with related types (e.g.
/// Current, Voltage).
/// </summary>
[Serializable]
[DataContract]
public class Resistance
{
public enum Unit
{
Ohms,
KiloOhms,
MegaOhms
}
public static IDictionary<Unit, List<string>> UnitAbbreviations = new Dictionary<Unit, List<string>>()
{
{Unit.Ohms, new List<string>(){ "Ohm" } },
{Unit.KiloOhms, new List<string>(){ "kOhm" } },
{Unit.MegaOhms, new List<string>(){ "MOhm" } },
};
private const Unit DefaultUnits = Unit.Ohms;
private const int KiloOhmsPerOhm = 1000;
private const int MegaOhmsPerOhm = 1000000;
[DataMember(Name = "Resistance", IsRequired = true)]
private double _resistance; // ohms
// map: unit => abbreviation, conversion method and property
private static IDictionary<Unit, UnitInfo<Resistance>> _unitInfo = new Dictionary<Unit, UnitInfo<Resistance>>()
{
{ Unit.Ohms, new UnitInfo<Resistance>(UnitAbbreviations[Unit.Ohms], FromOhms, typeof(Resistance).GetProperty("Ohms").GetGetMethod()) },
{ Unit.KiloOhms, new UnitInfo<Resistance>(UnitAbbreviations[Unit.KiloOhms], FromKiloOhms, typeof(Resistance).GetProperty("KiloOhms").GetGetMethod()) },
{ Unit.MegaOhms, new UnitInfo<Resistance>(UnitAbbreviations[Unit.MegaOhms], FromMegaOhms, typeof(Resistance).GetProperty("MegaOhms").GetGetMethod()) }
};
/// <summary>
/// Prevents a default instance of the <see cref="Resistance"/> class from being created.
/// Use FromXXX methods to create objects of this type.
/// </summary>
/// <exception cref="System.Exception">No one should be calling this, it is only here to prevent users from creating default object</exception>
private Resistance()
{
throw new InvalidOperationException("No one should be calling this, it is only here to prevent users from creating default object");
}
/// <summary>
/// ctor used by this class to create objects in FromXXX methods
/// </summary>
/// <param name="resistance">The resistance - ohms</param>
private Resistance(double resistance)
{
_resistance = resistance;
}
#region conversion properties
/// <summary>
/// Returns ohms as type double
/// </summary>
/// <value>
/// ohms
/// </value>
public double Ohms
{
get { return _resistance; }
}
/// <summary>
/// Returns kiloohms as type double
/// </summary>
/// <value>
/// kiloohms
/// </value>
public double KiloOhms
{
get { return _resistance / KiloOhmsPerOhm; }
}
/// <summary>
/// Returns megaohms as type double
/// </summary>
/// <value>
/// megaohms
/// </value>
public double MegaOhms
{
get { return _resistance / MegaOhmsPerOhm; }
}
#endregion
#region creation methods
/// <summary>
/// Returns Resistance object interpreting passed value as kiloohms
/// </summary>
/// <param name="kiloohms">kiloohms</param>
/// <returns></returns>
public static Resistance FromKiloOhms(double kiloOhms)
{
return new Resistance(kiloOhms * KiloOhmsPerOhm);
}
/// <summary>
/// Returns Resistance object interpreting passed value as megaohms
/// </summary>
/// <param name="megaohms">megaohms</param>
/// <returns></returns>
public static Resistance FromMegaOhms(double megaOhms)
{
return new Resistance(megaOhms * MegaOhmsPerOhm);
}
/// <summary>
/// Returns Resistance object interpreting passed value as ohms
/// </summary>
/// <param name="ohms">ohms</param>
/// <returns></returns>
public static Resistance FromOhms(double ohms)
{
return new Resistance(ohms);
}
#endregion
public override bool Equals(object obj)
{
Resistance r = obj as Resistance;
return (r == null) ? false : (this._resistance == r._resistance);
}
public override int GetHashCode()
{
return _resistance.GetHashCode();
}
#region binary operators
// not implementing %, &, |, ^, <<, >>
public static Resistance operator +(Resistance left, Resistance right)
{
if (null == left)
throw new ArgumentNullException("left", "Cannot add a null Resistance");
if (null == right)
throw new ArgumentNullException("right", "Cannot add null Resistance");
return new Resistance(left._resistance + right._resistance);
}
public static Resistance operator -(Resistance left, Resistance right)
{
if (null == left)
throw new ArgumentNullException("left", "Cannot subtract a null Resistance");
if (null == right)
throw new ArgumentNullException("right", "Cannot subtract a null Resistance");
return new Resistance(left._resistance - right._resistance);
}
public static Resistance operator *(Resistance resistance, double scalar)
{
if (null == resistance)
throw new ArgumentNullException("resistance", "Cannot multiply a null Resistance");
return new Resistance(resistance._resistance * scalar);
}
public static Resistance operator *(double scalar, Resistance resistance)
{
if (null == resistance)
throw new ArgumentNullException("resistance", "Cannot multiply a null Resistance");
return new Resistance(scalar * resistance._resistance);
}
public static Resistance operator /(Resistance resistance, double scalar)
{
if (null == resistance)
throw new ArgumentNullException("resistance", "Cannot divide a null Resistance");
if (0.0 == scalar)
throw new DivideByZeroException("Cannot divide Resistance by 0");
return new Resistance(resistance._resistance / scalar);
}
#endregion
#region comparison operators
public static bool operator ==(Resistance left, Resistance right)
{
bool bReturn = false;
if (object.ReferenceEquals(left, null))
{
if (object.ReferenceEquals(right, null))
{
//both are null, so we are ==
bReturn = true;
}
}
else
{
if (!object.ReferenceEquals(left, null) &&
!object.ReferenceEquals(right, null))
{
bReturn = left._resistance == right._resistance;
}
}
return bReturn;
}
public static bool operator !=(Resistance left, Resistance right)
{
return !(left == right);
}
public static bool operator <(Resistance left, Resistance right)
{
if (null == left)
throw new ArgumentNullException("left", "Cannot compare null Resistance");
if (null == right)
throw new ArgumentNullException("right", "Cannot compare null Resistance");
return (left._resistance < right._resistance);
}
public static bool operator >(Resistance left, Resistance right)
{
if (null == left)
throw new ArgumentNullException("left", "Cannot compare null Resistance");
if (null == right)
throw new ArgumentNullException("right", "Cannot compare null Resistance");
return (left._resistance > right._resistance);
}
public static bool operator <=(Resistance left, Resistance right)
{
if (null == left)
throw new ArgumentNullException("left", "Cannot compare null Resistance");
if (null == right)
throw new ArgumentNullException("right", "Cannot compare null Resistance");
return (left._resistance <= right._resistance);
}
public static bool operator >=(Resistance left, Resistance right)
{
if (null == left)
throw new ArgumentNullException("left", "Cannot compare null Resistance");
if (null == right)
throw new ArgumentNullException("right", "Cannot compare null Resistance");
return (left._resistance >= right._resistance);
}
#endregion
#region operators with non-resistance classes
/// <summary>
/// Implements the operator * for Voltage = Resistance / Current
/// </summary>
/// <param name="resistance">The resistance.</param>
/// <param name="current">The current.</param>
/// <returns>
/// Voltage
/// </returns>
public static Voltage operator *(Resistance resistance, Current current)
{
if (null == resistance)
throw new ArgumentNullException("resistance", "Cannot divide a null Resistance");
if (null == current)
throw new ArgumentNullException("current", "Cannot divide by a null Current");
if (0.0 == current.Amps)
throw new DivideByZeroException("Cannot divide Resistance by 0 Current");
return Voltage.FromVolts(resistance.Ohms * current.Amps);
}
#endregion
#region parsing
public static Resistance Parse(string s)
{
return Common.Parse(s, _unitInfo);
}
public static bool TryParse(string s, out Resistance value)
{
try
{
value = Resistance.Parse(s);
return true;
}
catch (Exception)
{
value = null;
return false;
}
}
#endregion
/// <summary>
/// Returns a string appended with default units (e.g. "1.23 m/sec^2").
/// </summary>
/// <returns>
/// A string that represents this instance
/// </returns>
public override string ToString()
{
return ToString(DefaultUnits);
}
/// <summary>
/// overload that returns a string appended with specified units (e.g. "1.23 ft/sec^2").
/// </summary>
/// <param name="units"></param>
/// <returns></returns>
public string ToString(Unit units)
{
double value = (double)_unitInfo[units].PropertyGetter.Invoke(this, null);
return $"{value} {_unitInfo[units].Abbreviation[0]}";
}
}
}

View File

@@ -0,0 +1,325 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.Serialization;
using System.Diagnostics.CodeAnalysis;
namespace Raytheon.Units
{
[Serializable]
[DataContract]
public class Temperature
{
public enum Unit
{
DegreesC,
DegreesF,
DegreesK
}
public static IDictionary<Unit, List<string>> UnitAbbreviations = new Dictionary<Unit, List<string>>()
{
{Unit.DegreesC, new List<string>(){ "C" } },
{Unit.DegreesF, new List<string>(){ "F" } },
{Unit.DegreesK, new List<string>(){ "K" } },
};
private const Unit DefaultUnits = Unit.DegreesC;
private const double CdegreesPerFdegree = 5.0 / 9.0;
private const double CtoF_Offset = 32.0;
private const double KtoC_Offset = 273.15;
[DataMember(Name = "Temperature", IsRequired = true)]
private double _temperature; // degrees C
// map: unit => abbreviation, conversion method and property
private static IDictionary<Unit, UnitInfo<Temperature>> _unitInfo = new Dictionary<Unit, UnitInfo<Temperature>>()
{
{ Unit.DegreesC, new UnitInfo<Temperature>(UnitAbbreviations[Unit.DegreesC], FromDegreesC, typeof(Temperature).GetProperty("DegreesC").GetGetMethod()) },
{ Unit.DegreesF, new UnitInfo<Temperature>(UnitAbbreviations[Unit.DegreesF], FromDegreesF, typeof(Temperature).GetProperty("DegreesF").GetGetMethod()) },
{ Unit.DegreesK, new UnitInfo<Temperature>(UnitAbbreviations[Unit.DegreesK], FromDegreesK, typeof(Temperature).GetProperty("DegreesK").GetGetMethod()) }
};
private Temperature()
{
throw new InvalidOperationException("No one should be calling this, it is only here to prevent users from creating default object");
}
private Temperature(double temperature)
{
_temperature = temperature;
}
#region output properties
public double DegreesC
{
get
{
return _temperature;
}
}
public double DegreesF
{
get
{
return (_temperature / CdegreesPerFdegree) + CtoF_Offset;
}
}
public double DegreesK
{
get
{
return DegreesC + KtoC_Offset;
}
}
#endregion
#region creation methods
public static Temperature FromDegreesC(double temperature)
{
return new Temperature(temperature);
}
public static Temperature FromDegreesF(double temperature)
{
return new Temperature((temperature - CtoF_Offset) * CdegreesPerFdegree);
}
public static Temperature FromDegreesK(double temperature)
{
return FromDegreesC(temperature - KtoC_Offset);
}
#endregion
#region add delta methods
public void Add(TemperatureDelta delta)
{
if (delta == null)
{
throw new ArgumentNullException("delta");
}
_temperature += delta.DegreesC;
}
public void AddDegreesC(double delta)
{
_temperature += TemperatureDelta.FromDegreesC(delta).DegreesC;
}
public void AddDegreesF(double delta)
{
_temperature += TemperatureDelta.FromDegreesF(delta).DegreesC;
}
public void AddDegreesK(double delta)
{
_temperature += TemperatureDelta.FromDegreesK(delta).DegreesC;
}
#endregion
#region binary operators
public static Temperature operator +(Temperature left, TemperatureDelta right)
{
if (null == left)
throw new ArgumentNullException("left", "Cannot add a null Temperature");
if (null == right)
throw new ArgumentNullException("right", "Cannot add null TemperatureDelta");
return new Temperature(left.DegreesC + right.DegreesC);
}
public static Temperature operator +(TemperatureDelta left, Temperature right)
{
if (null == left)
throw new ArgumentNullException("left", "Cannot add a null TemperatureDelta");
if (null == right)
throw new ArgumentNullException("right", "Cannot add null Temperature");
return new Temperature(left.DegreesC + right.DegreesC);
}
public static TemperatureDelta operator -(Temperature left, Temperature right)
{
if (null == left)
throw new ArgumentNullException("left", "Cannot add a null Temperature");
if (null == right)
throw new ArgumentNullException("right", "Cannot add null Temperature");
return TemperatureDelta.FromDegreesC(left.DegreesC - right.DegreesC);
}
public static Temperature operator -(Temperature left, TemperatureDelta right)
{
if (null == left)
throw new ArgumentNullException("left", "Cannot add a null Temperature");
if (null == right)
throw new ArgumentNullException("right", "Cannot add null TemperatureDelta");
return Temperature.FromDegreesC(left.DegreesC - right.DegreesC);
}
#endregion
#region comparison operators
public static bool operator ==(Temperature left, Temperature right)
{
bool bReturn = false;
if (object.ReferenceEquals(left, null))
{
if (object.ReferenceEquals(right, null))
{
//both are null, so we are ==
bReturn = true;
}
}
else
{
if (!object.ReferenceEquals(left, null) &&
!object.ReferenceEquals(right, null))
{
bReturn = left._temperature == right._temperature;
}
}
return bReturn;
}
public static bool operator !=(Temperature left, Temperature right)
{
return !(left == right);
}
public static bool operator <(Temperature left, Temperature right)
{
if (null == left)
throw new ArgumentNullException("left", "Cannot compare null Temperature");
if (null == right)
throw new ArgumentNullException("right", "Cannot compare null Temperature");
return (left._temperature < right._temperature);
}
public static bool operator >(Temperature left, Temperature right)
{
if (null == left)
throw new ArgumentNullException("left", "Cannot compare null Temperature");
if (null == right)
throw new ArgumentNullException("right", "Cannot compare null Temperature");
return (left._temperature > right._temperature);
}
public static bool operator <=(Temperature left, Temperature right)
{
if (null == left)
throw new ArgumentNullException("left", "Cannot compare null Temperature");
if (null == right)
throw new ArgumentNullException("right", "Cannot compare null Temperature");
return (left._temperature <= right._temperature);
}
public static bool operator >=(Temperature left, Temperature right)
{
if (null == left)
throw new ArgumentNullException("left", "Cannot compare null Temperature");
if (null == right)
throw new ArgumentNullException("right", "Cannot compare null Temperature");
return (left._temperature >= right._temperature);
}
#endregion
#region parsing
public static Temperature Parse(string s)
{
return Common.Parse(s, _unitInfo);
}
public static bool TryParse(string s, out Temperature value)
{
try
{
value = Temperature.Parse(s);
return true;
}
catch (Exception)
{
value = null;
return false;
}
}
#endregion
#region Object overrides
public override bool Equals(object obj)
{
Temperature t = obj as Temperature;
return (t == null) ? false : (this._temperature == t._temperature);
}
public override int GetHashCode()
{
return _temperature.GetHashCode();
}
/// <summary>
/// Returns a string appended with default units (e.g. "1.23 m/sec^2").
/// </summary>
/// <returns>
/// A string that represents this instance
/// </returns>
public override string ToString()
{
return ToString(DefaultUnits);
}
/// <summary>
/// overload that returns a string appended with specified units (e.g. "1.23 ft/sec^2").
/// </summary>
/// <param name="units"></param>
/// <returns></returns>
public string ToString(Unit units)
{
double value = (double)_unitInfo[units].PropertyGetter.Invoke(this, null);
return $"{value} {_unitInfo[units].Abbreviation[0]}";
}
#endregion
}
}

View File

@@ -0,0 +1,215 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.Serialization;
using System.Diagnostics.CodeAnalysis;
namespace Raytheon.Units
{
[Serializable]
[DataContract]
public class TemperatureDelta
{
public enum Unit
{
DegreesC,
DegreesF,
DegreesK
}
public static IDictionary<Unit, List<string>> UnitAbbreviations = new Dictionary<Unit, List<string>>()
{
{Unit.DegreesC, new List<string>(){ "C" } },
{Unit.DegreesF, new List<string>(){ "F" } },
{Unit.DegreesK, new List<string>(){ "K" } },
};
private const Unit DefaultUnits = Unit.DegreesC;
private const double CdegreesPerFdegree = 5.0 / 9.0;
[DataMember(Name = "Delta", IsRequired = true)]
private double _delta; // degrees C or K
// map: unit => abbreviation, conversion method and property
private static IDictionary<Unit, UnitInfo<TemperatureDelta>> _unitInfo = new Dictionary<Unit, UnitInfo<TemperatureDelta>>()
{
{ Unit.DegreesC, new UnitInfo<TemperatureDelta>(UnitAbbreviations[Unit.DegreesC], FromDegreesC, typeof(TemperatureDelta).GetProperty("DegreesC").GetGetMethod()) },
{ Unit.DegreesF, new UnitInfo<TemperatureDelta>(UnitAbbreviations[Unit.DegreesF], FromDegreesF, typeof(TemperatureDelta).GetProperty("DegreesF").GetGetMethod()) },
{ Unit.DegreesK, new UnitInfo<TemperatureDelta>(UnitAbbreviations[Unit.DegreesK], FromDegreesK, typeof(TemperatureDelta).GetProperty("DegreesK").GetGetMethod()) }
};
private TemperatureDelta()
{
throw new InvalidOperationException("No one should be calling this, it is only here to prevent users from creating default object");
}
private TemperatureDelta(double delta)
{
_delta = delta;
}
#region output properties
public double DegreesC
{
get
{
return _delta;
}
}
public double DegreesF
{
get
{
return _delta / CdegreesPerFdegree;
}
}
public double DegreesK
{
get
{
return _delta;
}
}
#endregion
#region creation methods
public static TemperatureDelta FromDegreesC(double temperature)
{
return new TemperatureDelta(temperature);
}
public static TemperatureDelta FromDegreesF(double temperature)
{
return new TemperatureDelta(temperature * CdegreesPerFdegree);
}
public static TemperatureDelta FromDegreesK(double temperature)
{
return new TemperatureDelta(temperature);
}
#endregion
// binary operators are in Temperature class
#region comparison operators
public static bool operator <(TemperatureDelta left, TemperatureDelta right)
{
if (null == left)
throw new ArgumentNullException("left", "Cannot compare null TemperatureDelta");
if (null == right)
throw new ArgumentNullException("right", "Cannot compare null TemperatureDelta");
return (left._delta < right._delta);
}
public static bool operator >(TemperatureDelta left, TemperatureDelta right)
{
if (null == left)
throw new ArgumentNullException("left", "Cannot compare null TemperatureDelta");
if (null == right)
throw new ArgumentNullException("right", "Cannot compare null TemperatureDelta");
return (left._delta > right._delta);
}
public static bool operator <=(TemperatureDelta left, TemperatureDelta right)
{
if (null == left)
throw new ArgumentNullException("left", "Cannot compare null TemperatureDelta");
if (null == right)
throw new ArgumentNullException("right", "Cannot compare null TemperatureDelta");
return (left._delta <= right._delta);
}
public static bool operator >=(TemperatureDelta left, TemperatureDelta right)
{
if (null == left)
throw new ArgumentNullException("left", "Cannot compare null TemperatureDelta");
if (null == right)
throw new ArgumentNullException("right", "Cannot compare null TemperatureDelta");
return (left._delta >= right._delta);
}
#endregion
#region parsing
public static TemperatureDelta Parse(string s)
{
return Common.Parse(s, _unitInfo);
}
public static bool TryParse(string s, out TemperatureDelta value)
{
try
{
value = TemperatureDelta.Parse(s);
return true;
}
catch (Exception)
{
value = null;
return false;
}
}
#endregion
#region Object overrides
public override bool Equals(object obj)
{
TemperatureDelta d = obj as TemperatureDelta;
return (d == null) ? false : (this._delta == d._delta);
}
public override int GetHashCode()
{
return _delta.GetHashCode();
}
/// <summary>
/// Returns a string appended with default units (e.g. "1.23 m/sec^2").
/// </summary>
/// <returns>
/// A string that represents this instance
/// </returns>
public override string ToString()
{
return ToString(DefaultUnits);
}
/// <summary>
/// overload that returns a string appended with specified units (e.g. "1.23 ft/sec^2").
/// </summary>
/// <param name="units"></param>
/// <returns></returns>
public string ToString(Unit units)
{
double value = (double)_unitInfo[units].PropertyGetter.Invoke(this, null);
return $"{value} {_unitInfo[units].Abbreviation[0]}";
}
#endregion
}
}

View File

@@ -0,0 +1,409 @@
using System;
using System.Text;
using System.Runtime.Serialization;
using System.Diagnostics.CodeAnalysis;
using System.Collections.Generic;
namespace Raytheon.Units
{
/// <summary>
/// This class represents a velocity.
///
/// It has no constructors. Instead, it provides multiple methods for creating objects of this
/// type. Those methods are of the form FromXXX, where XXX is a unit (e.g. FromMetersPerSec).
///
/// Properties (e.g. FeetPerSec) are provided to convert the value to other units and return
/// as type double.
///
/// Methods (operator overloads) are provided to perform calculations with related types (e.g.
/// Acceleration, Length).
/// </summary>
[Serializable]
[DataContract]
public class Velocity
{
public enum Unit
{
FeetPerSecond,
MetersPerSecond,
}
public static IDictionary<Unit, List<string>> UnitAbbreviations = new Dictionary<Unit, List<string>>()
{
{Unit.FeetPerSecond, new List<string>(){ "ft/sec" } },
{Unit.MetersPerSecond, new List<string>(){ "m/sec" } },
};
private const Unit DefaultUnits = Unit.MetersPerSecond;
private const double FeetPerMeter = 3.280839895013123;
[DataMember(Name = "Velocity", IsRequired = true)]
private double _velocity; // meters/second
// map: unit => abbreviation, conversion method and property
private static IDictionary<Unit, UnitInfo<Velocity>> _unitInfo = new Dictionary<Unit, UnitInfo<Velocity>>()
{
{ Unit.FeetPerSecond, new UnitInfo<Velocity>(UnitAbbreviations[Unit.FeetPerSecond], FromFeetPerSec, typeof(Velocity).GetProperty("FeetPerSec").GetGetMethod()) },
{ Unit.MetersPerSecond, new UnitInfo<Velocity>(UnitAbbreviations[Unit.MetersPerSecond], FromMetersPerSec, typeof(Velocity).GetProperty("MetersPerSec").GetGetMethod()) },
};
/// <summary>
/// Prevents a default instance of the <see cref="Velocity"/> class from being created.
/// Use FromXXX methods to create objects of this type.
/// </summary>
/// <exception cref="System.Exception">No one should be calling this, it is only here to prevent users from creating default object</exception>
private Velocity()
{
throw new InvalidOperationException("No one should be calling this, it is only here to prevent users from creating default object");
}
/// <summary>
/// ctor used by this class to create objects in FromXXX methods
/// </summary>
/// <param name="velocity">The velocity - m/sec.</param>
private Velocity(double velocity)
{
_velocity = velocity;
}
#region conversion properties
/// <summary>
/// Returns feet/sec as type double
/// </summary>
/// <value>
/// feet/sec
/// </value>
public double FeetPerSec
{
get { return _velocity * FeetPerMeter; }
}
/// <summary>
/// Returns meters/sec as type double
/// </summary>
/// <value>
/// meters/sec
/// </value>
public double MetersPerSec
{
get { return _velocity; }
}
#endregion
#region creation methods
/// <summary>
/// Returns Velocity object interpreting passed value as ft/sec
/// </summary>
/// <param name="feetPerSec">ft/sec</param>
/// <returns></returns>
public static Velocity FromFeetPerSec(double feetPerSec)
{
return new Velocity(feetPerSec / FeetPerMeter);
}
/// <summary>
/// Returns Velocity object interpreting passed value as meters/sec
/// </summary>
/// <param name="metersPerSec">meters/sec</param>
/// <returns></returns>
public static Velocity FromMetersPerSec(double metersPerSec)
{
return new Velocity(metersPerSec);
}
#endregion
public override bool Equals(object obj)
{
Velocity v = obj as Velocity;
return (v == null) ? false : (this._velocity == v._velocity);
}
public override int GetHashCode()
{
return _velocity.GetHashCode();
}
#region binary operators
// not implementing %, &, |, ^, <<, >>
public static Velocity operator +(Velocity left, Velocity right)
{
if (null == left)
throw new ArgumentNullException("left", "Cannot add a null Velocity");
if (null == right)
throw new ArgumentNullException("right", "Cannot add null Velocity");
return new Velocity(left._velocity + right._velocity);
}
public static Velocity operator -(Velocity left, Velocity right)
{
if (null == left)
throw new ArgumentNullException("left", "Cannot subtract a null Velocity");
if (null == right)
throw new ArgumentNullException("right", "Cannot subtract a null Velocity");
return new Velocity(left._velocity - right._velocity);
}
public static Velocity operator *(Velocity velocity, double scalar)
{
if (null == velocity)
throw new ArgumentNullException("velocity", "Cannot multiply a null Velocity");
return new Velocity(velocity._velocity * scalar);
}
public static Velocity operator *(double scalar, Velocity velocity)
{
if (null == velocity)
throw new ArgumentNullException("velocity", "Cannot multiply a null Velocity");
return new Velocity(scalar * velocity._velocity);
}
public static Velocity operator /(Velocity velocity, double scalar)
{
if (null == velocity)
throw new ArgumentNullException("velocity", "Cannot divide a null Velocity");
if (0.0 == scalar)
throw new DivideByZeroException("Cannot divide Velocity by 0");
return new Velocity(velocity._velocity / scalar);
}
#endregion
#region comparison operators
public static bool operator ==(Velocity left, Velocity right)
{
bool bReturn = false;
if (object.ReferenceEquals(left, null))
{
if (object.ReferenceEquals(right, null))
{
//both are null, so we are ==
bReturn = true;
}
}
else
{
if (!object.ReferenceEquals(left, null) &&
!object.ReferenceEquals(right, null))
{
bReturn = left._velocity == right._velocity;
}
}
return bReturn;
}
public static bool operator !=(Velocity left, Velocity right)
{
return !(left == right);
}
public static bool operator <(Velocity left, Velocity right)
{
if (null == left)
throw new ArgumentNullException("left", "Cannot compare null Velocity");
if (null == right)
throw new ArgumentNullException("right", "Cannot compare null Velocity");
return (left._velocity < right._velocity);
}
public static bool operator >(Velocity left, Velocity right)
{
if (null == left)
throw new ArgumentNullException("left", "Cannot compare null Velocity");
if (null == right)
throw new ArgumentNullException("right", "Cannot compare null Velocity");
return (left._velocity > right._velocity);
}
public static bool operator <=(Velocity left, Velocity right)
{
if (null == left)
throw new ArgumentNullException("left", "Cannot compare null Velocity");
if (null == right)
throw new ArgumentNullException("right", "Cannot compare null Velocity");
return (left._velocity <= right._velocity);
}
public static bool operator >=(Velocity left, Velocity right)
{
if (null == left)
throw new ArgumentNullException("left", "Cannot compare null Velocity");
if (null == right)
throw new ArgumentNullException("right", "Cannot compare null Velocity");
return (left._velocity >= right._velocity);
}
#endregion
#region operators with other classes
/// <summary>
/// Implements the operator * for Length = Velocity * PrecisionTimeSpan
/// </summary>
/// <param name="velocity">The velocity.</param>
/// <param name="time">The time.</param>
/// <returns>
/// Length
/// </returns>
public static Length operator *(Velocity velocity, PrecisionTimeSpan time)
{
if (null == velocity)
throw new ArgumentNullException("velocity", "Cannot multiply a null Velocity");
if (null == time)
throw new ArgumentNullException("time", "Cannot multiply a null PrecisionTimeSpan");
return Length.FromMeters(velocity.MetersPerSec * time.Seconds);
}
/// <summary>
/// Implements the operator * for Length = PrecisionTimeSpan * Velocity
/// </summary>
/// <param name="time">The time.</param>
/// <param name="velocity">The velocity.</param>
/// <returns>
/// Length
/// </returns>
public static Length operator *(PrecisionTimeSpan time, Velocity velocity)
{
if (null == time)
throw new ArgumentNullException("time", "Cannot divide a null PrecisionTimeSpan");
if (null == velocity)
throw new ArgumentNullException("velocity", "Cannot divide by a null Velocity");
if (0.0 == velocity.MetersPerSec)
throw new DivideByZeroException("Cannot divide Time Span by 0 Velocity");
return Length.FromMeters(time.Seconds * velocity.MetersPerSec);
}
/// <summary>
/// Implements the operator * for Acceleration = Velocity / PrecisionTimeSpan
/// </summary>
/// <param name="velocity">The velocity.</param>
/// <param name="time">The time.</param>
/// <returns>
/// Acceleration
/// </returns>
public static Acceleration operator /(Velocity velocity, PrecisionTimeSpan time)
{
if (null == velocity)
throw new ArgumentNullException("velocity", "Cannot divide a null Velocity");
if (null == time)
throw new ArgumentNullException("time", "Cannot divide by a null PrecisionTimeSpan");
if (0.0 == time.Milliseconds)
throw new DivideByZeroException("Cannot divide Velocity by 0 Time Span");
return Acceleration.FromMetersPerSecSqrd(velocity.MetersPerSec / time.Seconds);
}
/// <summary>
/// Implements the operator * for PrecisionTimeSpan = Velocity / Acceleration
/// </summary>
/// <param name="velocity">The velocity.</param>
/// <param name="time">The acceleration.</param>
/// <returns>
/// PrecisionTimeSpan
/// </returns>
public static PrecisionTimeSpan operator /(Velocity velocity, Acceleration acceleration)
{
if (null == velocity)
throw new ArgumentNullException("velocity", "Cannot divide a null Velocity");
if (null == acceleration)
throw new ArgumentNullException("acceleration", "Cannot divide by a null Acceleration");
if (0.0 == acceleration.MetersPerSecSqrd)
throw new DivideByZeroException("Cannot divide Velocity by 0 Acceleration");
return PrecisionTimeSpan.FromSeconds(velocity.MetersPerSec / acceleration.MetersPerSecSqrd);
}
#endregion
#region parsing
public static Velocity Parse(string s)
{
return Common.Parse(s, _unitInfo);
}
public static bool TryParse(string s, out Velocity value)
{
try
{
value = Velocity.Parse(s);
return true;
}
catch (Exception)
{
value = null;
return false;
}
}
#endregion
/// <summary>
/// Returns a string appended with default units (e.g. "1.23 m/sec^2").
/// </summary>
/// <returns>
/// A string that represents this instance
/// </returns>
public override string ToString()
{
return ToString(DefaultUnits);
}
/// <summary>
/// overload that returns a string appended with specified units (e.g. "1.23 ft/sec^2").
/// </summary>
/// <param name="units"></param>
/// <returns></returns>
public string ToString(Unit units)
{
double value = (double)_unitInfo[units].PropertyGetter.Invoke(this, null);
return $"{value} {_unitInfo[units].Abbreviation[0]}";
}
}
}

View File

@@ -0,0 +1,356 @@
using System;
using System.Text;
using System.Runtime.Serialization;
using System.Diagnostics.CodeAnalysis;
using System.Collections.Generic;
namespace Raytheon.Units
{
/// <summary>
/// This class represents a voltage.
///
/// It has no constructors. Instead, it provides multiple methods for creating objects of this
/// type. Those methods are of the form FromXXX, where XXX is a unit (e.g. FromVolts).
///
/// Properties (e.g. Volts) are provided to convert the value to other units and return
/// as type double.
///
/// Methods (operator overloads) are provided to perform calculations with related types (e.g.
/// Current, Resistance).
/// </summary>
[Serializable]
[DataContract]
public class Voltage
{
public enum Unit
{
Volts,
Millivolts
}
public static IDictionary<Unit, List<string>> UnitAbbreviations = new Dictionary<Unit, List<string>>()
{
{Unit.Volts, new List<string>(){ "V" } },
{Unit.Millivolts, new List<string>(){ "mV" } },
};
private const Unit DefaultUnits = Unit.Volts;
[DataMember(Name = "Voltage", IsRequired = true)]
private double _voltage; // volts
// map: unit => abbreviation, conversion method and property
private static IDictionary<Unit, UnitInfo<Voltage>> _unitInfo = new Dictionary<Unit, UnitInfo<Voltage>>()
{
{ Unit.Volts, new UnitInfo<Voltage>(UnitAbbreviations[Unit.Volts], FromVolts, typeof(Voltage).GetProperty("Volts").GetGetMethod()) },
{ Unit.Millivolts, new UnitInfo<Voltage>(UnitAbbreviations[Unit.Millivolts], FromMillivolts, typeof(Voltage).GetProperty("Millivolts").GetGetMethod()) }
};
/// <summary>
/// Prevents a default instance of the <see cref="Voltage"/> class from being created.
/// Use FromXXX methods to create objects of this type.
/// </summary>
/// <exception cref="System.Exception">No one should be calling this, it is only here to prevent users from creating default object</exception>
private Voltage()
{
throw new InvalidOperationException("No one should be calling this, it is only here to prevent users from creating default object");
}
/// <summary>
/// ctor used by this class to create objects in FromXXX methods
/// </summary>
/// <param name="voltage">The voltage - volts.</param>
private Voltage(double voltage)
{
_voltage = voltage;
}
#region conversion properties
public double Volts
{
get { return _voltage; }
}
public double Millivolts
{
get { return _voltage * 1000; }
}
#endregion
#region creation methods
/// <summary>
/// Returns Voltage object interpreting passed value as volts
/// </summary>
/// <param name="volts">volts</param>
/// <returns></returns>
public static Voltage FromVolts(double volts)
{
return new Voltage(volts);
}
/// <summary>
/// Returns Voltage object interpreting passed value as millivolts
/// </summary>
/// <param name="millivolts">millivolts</param>
/// <returns></returns>
public static Voltage FromMillivolts(double millivolts)
{
return new Voltage(millivolts / 1000);
}
#endregion
public override bool Equals(object obj)
{
Voltage v = obj as Voltage;
return (v == null) ? false : (this._voltage == v._voltage);
}
public override int GetHashCode()
{
return _voltage.GetHashCode();
}
#region binary operators
// not implementing %, &, |, ^, <<, >>
public static Voltage operator +(Voltage left, Voltage right)
{
if (null == left)
throw new ArgumentNullException("left", "Cannot add a null Voltage");
if (null == right)
throw new ArgumentNullException("right", "Cannot add null Voltage");
return new Voltage(left._voltage + right._voltage);
}
public static Voltage operator -(Voltage left, Voltage right)
{
if (null == left)
throw new ArgumentNullException("left", "Cannot subtract a null Voltage");
if (null == right)
throw new ArgumentNullException("right", "Cannot subtract a null Voltage");
return new Voltage(left._voltage - right._voltage);
}
public static Voltage operator *(Voltage voltage, double scalar)
{
if (null == voltage)
throw new ArgumentNullException("voltage", "Cannot multiply a null Voltage");
return new Voltage(voltage._voltage * scalar);
}
public static Voltage operator *(double scalar, Voltage voltage)
{
if (null == voltage)
throw new ArgumentNullException("voltage", "Cannot multiply a null Voltage");
return new Voltage(scalar * voltage._voltage);
}
public static Voltage operator /(Voltage voltage, double scalar)
{
if (null == voltage)
throw new ArgumentNullException("voltage", "Cannot divide a null Voltage");
if (0.0 == scalar)
throw new DivideByZeroException("Cannot divide Voltage by 0");
return new Voltage(voltage._voltage / scalar);
}
#endregion
#region comparison operators
public static bool operator ==(Voltage left, Voltage right)
{
bool bReturn = false;
if (object.ReferenceEquals(left, null))
{
if (object.ReferenceEquals(right, null))
{
//both are null, so we are ==
bReturn = true;
}
}
else
{
if (!object.ReferenceEquals(left, null) &&
!object.ReferenceEquals(right, null))
{
bReturn = left._voltage == right._voltage;
}
}
return bReturn;
}
public static bool operator !=(Voltage left, Voltage right)
{
return !(left == right);
}
public static bool operator <(Voltage left, Voltage right)
{
if (null == left)
throw new ArgumentNullException("left", "Cannot compare null Voltage");
if (null == right)
throw new ArgumentNullException("right", "Cannot compare null Voltage");
return (left._voltage < right._voltage);
}
public static bool operator >(Voltage left, Voltage right)
{
if (null == left)
throw new ArgumentNullException("left", "Cannot compare null Voltage");
if (null == right)
throw new ArgumentNullException("right", "Cannot compare null Voltage");
return (left._voltage > right._voltage);
}
public static bool operator <=(Voltage left, Voltage right)
{
if (null == left)
throw new ArgumentNullException("left", "Cannot compare null Voltage");
if (null == right)
throw new ArgumentNullException("right", "Cannot compare null Voltage");
return (left._voltage <= right._voltage);
}
public static bool operator >=(Voltage left, Voltage right)
{
if (null == left)
throw new ArgumentNullException("left", "Cannot compare null Voltage");
if (null == right)
throw new ArgumentNullException("right", "Cannot compare null Voltage");
return (left._voltage >= right._voltage);
}
#endregion
#region operators with non-Voltage classes
/// <summary>
/// Implements the operator * for Current = Voltage / Resistance
/// </summary>
/// <param name="voltage">The voltage.</param>
/// <param name="time">The resistance.</param>
/// <returns>
/// Current
/// </returns>
public static Current operator /(Voltage voltage, Resistance resistance)
{
if (null == voltage)
throw new ArgumentNullException("voltage", "Cannot divide a null Voltage");
if (null == resistance)
throw new ArgumentNullException("resistance", "Cannot divide by a null Resistance");
if (0.0 == resistance.Ohms)
throw new DivideByZeroException("Cannot divide Voltage by 0 Resistance");
return Current.FromAmps(voltage.Volts / resistance.Ohms);
}
/// <summary>
/// Implements the operator * for Resistance = Voltage / Current
/// </summary>
/// <param name="voltage">The voltage.</param>
/// <param name="time">The current.</param>
/// <returns>
/// Resistance
/// </returns>
public static Resistance operator /(Voltage voltage, Current current)
{
if (null == voltage)
throw new ArgumentNullException("voltage", "Cannot divide a null Voltage");
if (null == current)
throw new ArgumentNullException("current", "Cannot divide by a null Current");
if (0.0 == current.Amps)
throw new DivideByZeroException("Cannot divide Voltage by 0 Current");
return Resistance.FromOhms(voltage.Volts / current.Amps);
}
#endregion
#region parsing
public static Voltage Parse(string s)
{
return Common.Parse(s, _unitInfo);
}
public static bool TryParse(string s, out Voltage value)
{
try
{
value = Voltage.Parse(s);
return true;
}
catch (Exception)
{
value = null;
return false;
}
}
#endregion
/// <summary>
/// Returns a string appended with default units (e.g. "1.23 m/sec^2").
/// </summary>
/// <returns>
/// A string that represents this instance
/// </returns>
public override string ToString()
{
return ToString(DefaultUnits);
}
/// <summary>
/// overload that returns a string appended with specified units (e.g. "1.23 ft/sec^2").
/// </summary>
/// <param name="units"></param>
/// <returns></returns>
public string ToString(Unit units)
{
double value = (double)_unitInfo[units].PropertyGetter.Invoke(this, null);
return $"{value} {_unitInfo[units].Abbreviation[0]}";
}
}
}