mirror of
https://github.com/greenshot/greenshot
synced 2025-08-14 18:57:28 -07:00
Refactored the ini code to be more "OO", making it possible to reset a value which was needed to implement an auto-repair for certain settings. This was intiated by Bug #3509754, which hat the reason that somehow the Hotkey name was corrupt.
git-svn-id: http://svn.code.sf.net/p/greenshot/code/trunk@1721 7dccd23d-a4a3-4e1f-8c07-b4c1b4018ab4
This commit is contained in:
parent
20d4fb693f
commit
4b3f7ba0a5
10 changed files with 507 additions and 440 deletions
|
@ -192,7 +192,10 @@ namespace Greenshot.Destinations {
|
|||
using (Image image = surface.GetImageForExport()) {
|
||||
tmpFile = ImageOutput.SaveNamedTmpFile(image, captureDetails, conf.OutputFileFormat, conf.OutputFileJpegQuality, conf.OutputFileReduceColors);
|
||||
}
|
||||
} else {
|
||||
LOG.InfoFormat("Using already available file: {0}", tmpFile);
|
||||
}
|
||||
|
||||
// Create a attachment name for the image
|
||||
string attachmentName = captureDetails.Title;
|
||||
if (!string.IsNullOrEmpty(attachmentName)) {
|
||||
|
|
|
@ -450,7 +450,45 @@ namespace Greenshot {
|
|||
}
|
||||
base.WndProc(ref m);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Helper method to cleanly register a hotkey
|
||||
/// </summary>
|
||||
/// <param name="failedKeys"></param>
|
||||
/// <param name="functionName"></param>
|
||||
/// <param name="hotkeyString"></param>
|
||||
/// <param name="handler"></param>
|
||||
/// <returns></returns>
|
||||
private static bool RegisterHotkey(StringBuilder failedKeys, string functionName, string hotkeyString, HotKeyHandler handler) {
|
||||
Keys modifierKeyCode = HotkeyControl.HotkeyModifiersFromString(hotkeyString);
|
||||
Keys virtualKeyCode = HotkeyControl.HotkeyFromString(hotkeyString);
|
||||
if (HotkeyControl.RegisterHotKey(modifierKeyCode, virtualKeyCode, handler) < 0) {
|
||||
LOG.DebugFormat("Failed to register {0} to hotkey: {1}", functionName, hotkeyString);
|
||||
if (failedKeys.Length > 0) {
|
||||
failedKeys.Append(", ");
|
||||
}
|
||||
failedKeys.Append(hotkeyString);
|
||||
return false;
|
||||
} else {
|
||||
LOG.DebugFormat("Registered {0} to hotkey: {1}", functionName, hotkeyString);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private static bool RegisterWrapper(StringBuilder failedKeys, string functionName, string configurationKey, HotKeyHandler handler) {
|
||||
IniValue hotkeyValue = conf.Values[configurationKey];
|
||||
try {
|
||||
return RegisterHotkey(failedKeys, functionName, hotkeyValue.Value.ToString(), handler);
|
||||
} catch (Exception ex) {
|
||||
LOG.Warn(ex);
|
||||
LOG.WarnFormat("Repairing the hotkey for {0}, stored under {1} from '{2}' to '{3}'", functionName, configurationKey, hotkeyValue.Value, hotkeyValue.Attributes.DefaultValue);
|
||||
// when getting an exception the key wasn't found: reset the hotkey value
|
||||
hotkeyValue.UseValueOrDefault(null);
|
||||
hotkeyValue.ContainingIniSection.IsDirty = true;
|
||||
return RegisterHotkey(failedKeys, functionName, hotkeyValue.Value.ToString(), handler);
|
||||
}
|
||||
}
|
||||
|
||||
public static void RegisterHotkeys() {
|
||||
if (instance == null) {
|
||||
return;
|
||||
|
@ -458,64 +496,20 @@ namespace Greenshot {
|
|||
bool success = true;
|
||||
StringBuilder failedKeys = new StringBuilder();
|
||||
|
||||
// Capture region
|
||||
if (HotkeyControl.RegisterHotKey(conf.RegionHotkey, new HotKeyHandler(instance.CaptureRegion)) < 0) {
|
||||
LOG.DebugFormat("Failed to register CaptureRegion to hotkey: {0}", conf.RegionHotkey);
|
||||
if (!RegisterWrapper(failedKeys, "CaptureRegion", "RegionHotkey", new HotKeyHandler(instance.CaptureRegion))) {
|
||||
success = false;
|
||||
if(failedKeys.Length > 0) {
|
||||
failedKeys.Append(", ");
|
||||
}
|
||||
failedKeys.Append(conf.RegionHotkey);
|
||||
} else {
|
||||
LOG.DebugFormat("Registered CaptureRegion to hotkey: {0}", conf.RegionHotkey);
|
||||
}
|
||||
|
||||
// Capture window
|
||||
if (HotkeyControl.RegisterHotKey(conf.WindowHotkey, new HotKeyHandler(instance.CaptureWindow)) < 0) {
|
||||
LOG.DebugFormat("Failed to register CaptureWindow to hotkey: {0}", conf.WindowHotkey);
|
||||
if (!RegisterWrapper(failedKeys, "CaptureWindow", "WindowHotkey", new HotKeyHandler(instance.CaptureWindow))) {
|
||||
success = false;
|
||||
if(failedKeys.Length > 0) {
|
||||
failedKeys.Append(", ");
|
||||
}
|
||||
failedKeys.Append(conf.WindowHotkey);
|
||||
} else {
|
||||
LOG.DebugFormat("Registered CaptureWindow to hotkey: {0}", conf.WindowHotkey);
|
||||
}
|
||||
|
||||
// Capture fullScreen
|
||||
if (HotkeyControl.RegisterHotKey(conf.FullscreenHotkey, new HotKeyHandler(instance.CaptureFullScreen)) < 0) {
|
||||
LOG.DebugFormat("Failed to register CaptureFullScreen to hotkey: {0}", conf.FullscreenHotkey);
|
||||
if (!RegisterWrapper(failedKeys, "CaptureFullScreen", "FullscreenHotkey", new HotKeyHandler(instance.CaptureFullScreen))) {
|
||||
success = false;
|
||||
if(failedKeys.Length > 0) {
|
||||
failedKeys.Append(", ");
|
||||
}
|
||||
failedKeys.Append(conf.FullscreenHotkey);
|
||||
} else {
|
||||
LOG.DebugFormat("Registered CaptureFullScreen to hotkey: {0}", conf.FullscreenHotkey);
|
||||
}
|
||||
|
||||
// Capture last region
|
||||
if (HotkeyControl.RegisterHotKey(conf.LastregionHotkey, new HotKeyHandler(instance.CaptureLastRegion)) < 0) {
|
||||
LOG.DebugFormat("Failed to register CaptureLastRegion to hotkey: {0}", conf.LastregionHotkey);
|
||||
if (!RegisterWrapper(failedKeys, "CaptureLastRegion", "LastregionHotkey", new HotKeyHandler(instance.CaptureLastRegion))) {
|
||||
success = false;
|
||||
if(failedKeys.Length > 0) {
|
||||
failedKeys.Append(", ");
|
||||
}
|
||||
failedKeys.Append(conf.LastregionHotkey);
|
||||
} else {
|
||||
LOG.DebugFormat("Registered CaptureLastRegion to hotkey: {0}", conf.LastregionHotkey);
|
||||
}
|
||||
|
||||
// Capture IE
|
||||
if (HotkeyControl.RegisterHotKey(conf.IEHotkey, new HotKeyHandler(instance.CaptureIE)) < 0) {
|
||||
LOG.DebugFormat("Failed to register CaptureIE to hotkey: {0}", conf.IEHotkey);
|
||||
if (!RegisterWrapper(failedKeys, "CaptureIE", "IEHotkey", new HotKeyHandler(instance.CaptureIE))) {
|
||||
success = false;
|
||||
if(failedKeys.Length > 0) {
|
||||
failedKeys.Append(", ");
|
||||
}
|
||||
failedKeys.Append(conf.IEHotkey);
|
||||
} else {
|
||||
LOG.DebugFormat("Registered CaptureIE to hotkey: {0}", conf.IEHotkey);
|
||||
}
|
||||
|
||||
if (!success) {
|
||||
|
|
|
@ -75,7 +75,10 @@ namespace Greenshot.Helpers {
|
|||
List<IDestination> destinations = new List<IDestination>();
|
||||
destinations.AddRange(RegisteredDestinations.Values);
|
||||
foreach(IGreenshotPlugin plugin in PluginHelper.instance.Plugins.Values) {
|
||||
destinations.AddRange(plugin.Destinations());
|
||||
var dests = plugin.Destinations();
|
||||
if (dests != null) {
|
||||
destinations.AddRange(dests);
|
||||
}
|
||||
}
|
||||
destinations.Sort();
|
||||
return destinations;
|
||||
|
|
|
@ -125,7 +125,7 @@ namespace Greenshot.Helpers {
|
|||
exceptionText.AppendLine(EnvironmentInfo.ExceptionToString(exception));
|
||||
exceptionText.AppendLine("Configuration dump:");
|
||||
using (TextWriter writer = new StringWriter(exceptionText)) {
|
||||
IniConfig.SaveIniSectionToWriter(writer, IniConfig.GetIniSection<CoreConfiguration>(), true);
|
||||
IniConfig.GetIniSection<CoreConfiguration>().Write(writer, true);
|
||||
}
|
||||
|
||||
return exceptionText.ToString();
|
||||
|
|
|
@ -194,7 +194,8 @@ namespace GreenshotPlugin.Core {
|
|||
if (productName != null && NoDWMCaptureForProduct.Contains(productName.ToLower())) {
|
||||
return false;
|
||||
}
|
||||
} catch {
|
||||
} catch (Exception ex) {
|
||||
LOG.Warn(ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -214,7 +215,8 @@ namespace GreenshotPlugin.Core {
|
|||
if (productName != null && NoGDICaptureForProduct.Contains(productName.ToLower())) {
|
||||
return false;
|
||||
}
|
||||
} catch {
|
||||
} catch (Exception ex) {
|
||||
LOG.Warn(ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -250,7 +252,8 @@ namespace GreenshotPlugin.Core {
|
|||
try {
|
||||
Directory.CreateDirectory(pafOutputFilePath);
|
||||
return pafOutputFilePath;
|
||||
} catch(Exception) {
|
||||
} catch (Exception ex) {
|
||||
LOG.Warn(ex);
|
||||
// Problem creating directory, fallback to Desktop
|
||||
}
|
||||
} else {
|
||||
|
|
|
@ -48,7 +48,8 @@ namespace GreenshotPlugin.Core {
|
|||
}
|
||||
}
|
||||
}
|
||||
} catch {
|
||||
} catch (Exception ex) {
|
||||
LOG.Warn(ex);
|
||||
}
|
||||
}
|
||||
return list;
|
||||
|
|
|
@ -244,7 +244,7 @@ namespace GreenshotPlugin.Core {
|
|||
return iconCache[filename];
|
||||
} catch (Exception ex) {
|
||||
LOG.WarnFormat("Couldn't get icon for window {0} due to: {1}", Text, ex.Message);
|
||||
};
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
@ -567,7 +567,9 @@ namespace GreenshotPlugin.Core {
|
|||
if (process != null) {
|
||||
return process;
|
||||
}
|
||||
} catch {}
|
||||
} catch (Exception ex) {
|
||||
LOG.Warn(ex);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
@ -1358,7 +1360,9 @@ namespace GreenshotPlugin.Core {
|
|||
get {
|
||||
try {
|
||||
return "Greenshot".Equals(Process.MainModule.FileVersionInfo.ProductName);
|
||||
} catch {}
|
||||
} catch (Exception ex) {
|
||||
LOG.Warn(ex);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -221,7 +221,7 @@ namespace Greenshot.IniFile {
|
|||
Read(CreateIniLocation(configName + FIXED_POSTFIX + INI_EXTENSION));
|
||||
|
||||
foreach (IniSection section in sectionMap.Values) {
|
||||
FillIniSection(section);
|
||||
section.Fill(PropertiesForSection(section));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -278,8 +278,7 @@ namespace Greenshot.IniFile {
|
|||
|
||||
// Store for later save & retrieval
|
||||
sectionMap.Add(sectionName, section);
|
||||
FillIniSection(section);
|
||||
//LOG.Debug("Returning newly mapped section " + sectionName);
|
||||
section.Fill(PropertiesForSection(section));
|
||||
}
|
||||
if (section.IsDirty) {
|
||||
LOG.DebugFormat("Section {0} is marked dirty, saving!", sectionName);
|
||||
|
@ -288,7 +287,7 @@ namespace Greenshot.IniFile {
|
|||
return section;
|
||||
}
|
||||
|
||||
private static void FillIniSection(IniSection section) {
|
||||
public static Dictionary<string, string> PropertiesForSection(IniSection section) {
|
||||
Type iniSectionType = section.GetType();
|
||||
string sectionName = getSectionName(iniSectionType);
|
||||
// Get the properties for the section
|
||||
|
@ -299,279 +298,7 @@ namespace Greenshot.IniFile {
|
|||
sections.Add(sectionName, new Dictionary<string, string>());
|
||||
properties = sections[sectionName];
|
||||
}
|
||||
|
||||
// Iterate over the members and create IniValueContainers
|
||||
foreach (FieldInfo fieldInfo in iniSectionType.GetFields()) {
|
||||
if (Attribute.IsDefined(fieldInfo, typeof(IniPropertyAttribute))) {
|
||||
if (!section.Values.ContainsKey(fieldInfo.Name)) {
|
||||
IniPropertyAttribute iniPropertyAttribute = (IniPropertyAttribute)fieldInfo.GetCustomAttributes(typeof(IniPropertyAttribute), false)[0];
|
||||
section.Values.Add(fieldInfo.Name, new IniValue(section, fieldInfo, iniPropertyAttribute));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach (PropertyInfo propertyInfo in iniSectionType.GetProperties()) {
|
||||
if (Attribute.IsDefined(propertyInfo, typeof(IniPropertyAttribute))) {
|
||||
if (!section.Values.ContainsKey(propertyInfo.Name)) {
|
||||
IniPropertyAttribute iniPropertyAttribute = (IniPropertyAttribute)propertyInfo.GetCustomAttributes(typeof(IniPropertyAttribute), false)[0];
|
||||
section.Values.Add(propertyInfo.Name, new IniValue(section, propertyInfo, iniPropertyAttribute));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach (string fieldName in section.Values.Keys) {
|
||||
IniValue iniValue = section.Values[fieldName];
|
||||
string propertyName = iniValue.Attributes.Name;
|
||||
string propertyDefaultValue = iniValue.Attributes.DefaultValue;
|
||||
|
||||
// Get the value from the ini file, if there is none take the default
|
||||
if (!properties.ContainsKey(propertyName) && propertyDefaultValue != null) {
|
||||
// Mark as dirty, we didn't use properties from the file (even defaults from the default file are allowed)
|
||||
section.IsDirty = true;
|
||||
//LOG.Debug("Passing default: " + propertyName + "=" + propertyDefaultValue);
|
||||
}
|
||||
|
||||
// Try to get the field value from the properties or use the default value
|
||||
object fieldValue = null;
|
||||
try {
|
||||
fieldValue = CreateValue(section, sectionName, iniValue);
|
||||
} catch (Exception) {
|
||||
//LOG.Warn("Couldn't parse field: " + sectionName + "." + propertyName, e);
|
||||
}
|
||||
|
||||
// If still no value, e.g. due to an exception, check if the GetDefault delivers a value
|
||||
if (fieldValue == null) {
|
||||
// Use GetDefault to fill the field if none is set
|
||||
fieldValue = section.GetDefault(propertyName);
|
||||
}
|
||||
|
||||
// Still no value? Log warning
|
||||
if (fieldValue == null) {
|
||||
LOG.WarnFormat("Property {0} has no value or default value.", propertyName);
|
||||
}
|
||||
|
||||
// Set the value
|
||||
try {
|
||||
iniValue.Value = fieldValue;
|
||||
} catch (Exception) {
|
||||
//LOG.Warn("Couldn't set field: " + sectionName + "." + propertyName, e);
|
||||
}
|
||||
}
|
||||
section.AfterLoad();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Helper method for creating a value
|
||||
/// </summary>
|
||||
/// <param name="section">IniSection</param>
|
||||
/// <param name="sectionName">string with name of section</param>
|
||||
/// <param name="iniValue">IniValue</param>
|
||||
/// <returns></returns>
|
||||
private static object CreateValue(IniSection section, string sectionName, IniValue iniValue) {
|
||||
string propertyName = iniValue.Attributes.Name;
|
||||
string defaultValue = iniValue.Attributes.DefaultValue;
|
||||
string arraySeparator = iniValue.Attributes.Separator;
|
||||
// Get the type, or the underlying type for nullables
|
||||
Type valueType = iniValue.ValueType;
|
||||
|
||||
Dictionary<string, string> properties = sections[sectionName];
|
||||
bool defaultUsed = false;
|
||||
string propertyValue = null;
|
||||
object defaultValueFromConfig = null;
|
||||
if (properties.ContainsKey(propertyName) && properties[propertyName] != null) {
|
||||
propertyValue = section.PreCheckValue(propertyName, properties[propertyName]);
|
||||
} else if (defaultValue != null && defaultValue.Trim().Length != 0) {
|
||||
propertyValue = defaultValue;
|
||||
defaultUsed = true;
|
||||
} else {
|
||||
LOG.DebugFormat("Property {0} has no value or default value, this might be corrected later!", propertyName);
|
||||
// Check if the developer implemented a default for the property
|
||||
defaultValueFromConfig = section.GetDefault(propertyName);
|
||||
if (defaultValueFromConfig != null) {
|
||||
LOG.DebugFormat("Default for Property {0} implemented!", propertyName);
|
||||
} else {
|
||||
if (iniValue.Attributes.ExcludeIfNull) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Now set the value
|
||||
if (valueType.IsGenericType && valueType.GetGenericTypeDefinition() == typeof(List<>)) {
|
||||
object list = Activator.CreateInstance(valueType);
|
||||
// Logic for List<>
|
||||
if (propertyValue == null) {
|
||||
if (defaultValueFromConfig != null) {
|
||||
return defaultValueFromConfig;
|
||||
}
|
||||
return list;
|
||||
}
|
||||
string[] arrayValues = propertyValue.Split(new string[] { arraySeparator }, StringSplitOptions.None);
|
||||
if (arrayValues == null || arrayValues.Length == 0) {
|
||||
return list;
|
||||
}
|
||||
bool addedElements = false;
|
||||
bool parseProblems = false;
|
||||
MethodInfo addMethodInfo = valueType.GetMethod("Add");
|
||||
|
||||
foreach (string arrayValue in arrayValues) {
|
||||
if (arrayValue != null && arrayValue.Length > 0) {
|
||||
object newValue = null;
|
||||
try {
|
||||
newValue = ConvertValueToValueType(valueType.GetGenericArguments()[0], arrayValue);
|
||||
} catch (Exception) {
|
||||
//LOG.Error("Problem converting " + arrayValue + " to type " + fieldType.FullName, e);
|
||||
parseProblems = true;
|
||||
}
|
||||
if (newValue != null) {
|
||||
addMethodInfo.Invoke(list, new object[] { newValue });
|
||||
addedElements = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Try to fallback on a default
|
||||
if (!addedElements && parseProblems) {
|
||||
try {
|
||||
object fallbackValue = ConvertValueToValueType(valueType.GetGenericArguments()[0], defaultValue);
|
||||
addMethodInfo.Invoke(list, new object[] { fallbackValue });
|
||||
return list;
|
||||
} catch (Exception) {
|
||||
//LOG.Error("Problem converting " + defaultValue + " to type " + fieldType.FullName, e);
|
||||
}
|
||||
}
|
||||
|
||||
return list;
|
||||
} else if (valueType.IsGenericType && valueType.GetGenericTypeDefinition() == typeof(Dictionary<,>)) {
|
||||
// Logic for Dictionary<,>
|
||||
Type type1 = valueType.GetGenericArguments()[0];
|
||||
Type type2 = valueType.GetGenericArguments()[1];
|
||||
//LOG.Info(String.Format("Found Dictionary<{0},{1}>", type1.Name, type2.Name));
|
||||
object dictionary = Activator.CreateInstance(valueType);
|
||||
MethodInfo addMethodInfo = valueType.GetMethod("Add");
|
||||
bool addedElements = false;
|
||||
foreach (string key in properties.Keys) {
|
||||
if (key != null && key.StartsWith(propertyName + ".")) {
|
||||
// What "key" do we need to store it under?
|
||||
string subPropertyName = key.Substring(propertyName.Length + 1);
|
||||
string stringValue = properties[key];
|
||||
object newValue1 = null;
|
||||
object newValue2 = null;
|
||||
try {
|
||||
newValue1 = ConvertValueToValueType(type1, subPropertyName);
|
||||
} catch (Exception) {
|
||||
//LOG.Error("Problem converting " + subPropertyName + " to type " + type1.FullName, e);
|
||||
}
|
||||
try {
|
||||
newValue2 = ConvertValueToValueType(type2, stringValue);
|
||||
} catch (Exception) {
|
||||
//LOG.Error("Problem converting " + stringValue + " to type " + type2.FullName, e);
|
||||
}
|
||||
addMethodInfo.Invoke(dictionary, new object[] { newValue1, newValue2 });
|
||||
addedElements = true;
|
||||
}
|
||||
}
|
||||
// No need to return something that isn't filled!
|
||||
if (addedElements) {
|
||||
return dictionary;
|
||||
} else if (defaultValueFromConfig != null) {
|
||||
return defaultValueFromConfig;
|
||||
}
|
||||
} if (defaultValueFromConfig != null) {
|
||||
return defaultValueFromConfig;
|
||||
} else {
|
||||
if (valueType.IsGenericType && valueType.GetGenericTypeDefinition().Equals(typeof(Nullable<>))) {
|
||||
// We are dealing with a generic type that is nullable
|
||||
valueType = Nullable.GetUnderlyingType(valueType);
|
||||
}
|
||||
object newValue = null;
|
||||
try {
|
||||
newValue = ConvertValueToValueType(valueType, propertyValue);
|
||||
} catch (Exception) {
|
||||
newValue = null;
|
||||
if (!defaultUsed) {
|
||||
try {
|
||||
newValue = ConvertValueToValueType(valueType, defaultValue);
|
||||
} catch (Exception) {
|
||||
//LOG.Error("Problem converting " + propertyValue + " to type " + fieldType.FullName, e2);
|
||||
}
|
||||
} else {
|
||||
//LOG.Error("Problem converting " + propertyValue + " to type " + fieldType.FullName, e1);
|
||||
}
|
||||
}
|
||||
return newValue;
|
||||
}
|
||||
}
|
||||
|
||||
private static object ConvertValueToValueType(Type valueType, string valueString) {
|
||||
if (valueString == null) {
|
||||
return null;
|
||||
}
|
||||
if (valueType == typeof(string)) {
|
||||
return valueString;
|
||||
}
|
||||
TypeConverter converter = TypeDescriptor.GetConverter(valueType);
|
||||
//LOG.Debug("No convertor for " + fieldType.ToString());
|
||||
if (valueType == typeof(object) && valueString.Length > 0) {
|
||||
//LOG.Debug("Parsing: " + valueString);
|
||||
string[] values = valueString.Split(new Char[] { ':' });
|
||||
//LOG.Debug("Type: " + values[0]);
|
||||
//LOG.Debug("Value: " + values[1]);
|
||||
Type fieldTypeForValue = Type.GetType(values[0], true);
|
||||
//LOG.Debug("Type after GetType: " + fieldTypeForValue);
|
||||
return ConvertValueToValueType(fieldTypeForValue, values[1]);
|
||||
} else if (converter != null) {
|
||||
return converter.ConvertFromInvariantString(valueString);
|
||||
} else if (valueType.IsEnum) {
|
||||
if (valueString.Length > 0) {
|
||||
try {
|
||||
return Enum.Parse(valueType, valueString);
|
||||
} catch (ArgumentException ae) {
|
||||
//LOG.InfoFormat("Couldn't match {0} to {1}, trying case-insentive match", valueString, fieldType);
|
||||
foreach (Enum enumValue in Enum.GetValues(valueType)) {
|
||||
if (enumValue.ToString().Equals(valueString, StringComparison.InvariantCultureIgnoreCase)) {
|
||||
//LOG.Info("Match found...");
|
||||
return enumValue;
|
||||
}
|
||||
}
|
||||
throw ae;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static string ConvertValueToString(Type valueType, object valueObject) {
|
||||
if (valueObject == null) {
|
||||
// If there is nothing, deliver nothing!
|
||||
return "";
|
||||
}
|
||||
if (valueType == typeof(object)) {
|
||||
// object to String, this is the hardest
|
||||
// Format will be "FQTypename[,Assemblyname]:Value"
|
||||
|
||||
// Get the type so we can call ourselves recursive
|
||||
Type objectType = valueObject.GetType();
|
||||
|
||||
// Get the value as string
|
||||
string ourValue = ConvertValueToString(objectType, valueObject);
|
||||
|
||||
// Get the valuetype as string
|
||||
string valueTypeName = objectType.FullName;
|
||||
// Find the assembly name and only append it if it's not already in the fqtypename (like System.Drawing)
|
||||
string assemblyName = objectType.Assembly.FullName;
|
||||
// correct assemblyName, this also has version information etc.
|
||||
if (assemblyName.StartsWith("Green")) {
|
||||
assemblyName = assemblyName.Substring(0, assemblyName.IndexOf(','));
|
||||
}
|
||||
return String.Format("{0},{1}:{2}", valueTypeName, assemblyName, ourValue);
|
||||
} else {
|
||||
TypeConverter converter = TypeDescriptor.GetConverter(valueType);
|
||||
if (converter != null) {
|
||||
return converter.ConvertToInvariantString(valueObject);
|
||||
}
|
||||
}
|
||||
// All other types
|
||||
return valueObject.ToString();
|
||||
return properties;
|
||||
}
|
||||
|
||||
private static string getSectionName(Type iniSectionType) {
|
||||
|
@ -589,101 +316,12 @@ namespace Greenshot.IniFile {
|
|||
string iniLocation = CreateIniLocation(configName + INI_EXTENSION);
|
||||
try {
|
||||
SaveInternally(iniLocation);
|
||||
} catch (Exception) {
|
||||
//LOG.Error("A problem occured while writing the configuration file to: " + iniLocation, e);
|
||||
} catch (Exception ex) {
|
||||
LOG.Error("A problem occured while writing the configuration file to: " + iniLocation);
|
||||
LOG.Error(ex);
|
||||
}
|
||||
}
|
||||
|
||||
public static void SaveIniSectionToWriter(TextWriter writer, IniSection section, bool onlyProperties) {
|
||||
section.BeforeSave();
|
||||
Type classType = section.GetType();
|
||||
Attribute[] classAttributes = Attribute.GetCustomAttributes(classType);
|
||||
foreach (Attribute attribute in classAttributes) {
|
||||
if (attribute is IniSectionAttribute) {
|
||||
IniSectionAttribute iniSectionAttribute = (IniSectionAttribute)attribute;
|
||||
if (!onlyProperties) {
|
||||
writer.WriteLine("; {0}", iniSectionAttribute.Description);
|
||||
}
|
||||
writer.WriteLine("[{0}]", iniSectionAttribute.Name);
|
||||
|
||||
// Iterate over the members and fill them
|
||||
List<MemberInfo> members = new List<MemberInfo>();
|
||||
|
||||
foreach (FieldInfo fieldInfo in classType.GetFields()) {
|
||||
members.Add(fieldInfo);
|
||||
}
|
||||
foreach (PropertyInfo propertyInfo in classType.GetProperties()) {
|
||||
members.Add(propertyInfo);
|
||||
}
|
||||
|
||||
foreach (MemberInfo member in members) {
|
||||
if (Attribute.IsDefined(member, typeof(IniPropertyAttribute))) {
|
||||
IniPropertyAttribute iniPropertyAttribute = (IniPropertyAttribute)member.GetCustomAttributes(typeof(IniPropertyAttribute), false)[0];
|
||||
object propertyValue;
|
||||
Type valueType;
|
||||
if (member is FieldInfo) {
|
||||
propertyValue = ((FieldInfo)member).GetValue(section);
|
||||
valueType = ((FieldInfo)member).FieldType;
|
||||
} else if (member is PropertyInfo) {
|
||||
propertyValue = ((PropertyInfo)member).GetValue(section, null);
|
||||
valueType = ((PropertyInfo)member).PropertyType;
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (propertyValue == null) {
|
||||
if (iniPropertyAttribute.ExcludeIfNull) {
|
||||
continue;
|
||||
}
|
||||
propertyValue = iniPropertyAttribute.DefaultValue;
|
||||
valueType = typeof(string);
|
||||
}
|
||||
|
||||
if (!onlyProperties) {
|
||||
writer.WriteLine("; {0}", iniPropertyAttribute.Description);
|
||||
}
|
||||
if (valueType.IsGenericType && valueType.GetGenericTypeDefinition() == typeof(List<>)) {
|
||||
Type specificValueType = valueType.GetGenericArguments()[0];
|
||||
writer.Write("{0}=", iniPropertyAttribute.Name);
|
||||
int listCount = (int)valueType.GetProperty("Count").GetValue(propertyValue, null);
|
||||
// Loop though generic list
|
||||
for (int index = 0; index < listCount; index++) {
|
||||
object item = valueType.GetMethod("get_Item").Invoke(propertyValue, new object[] { index });
|
||||
|
||||
// Now you have an instance of the item in the generic list
|
||||
if (index < listCount - 1) {
|
||||
writer.Write("{0}" + iniPropertyAttribute.Separator, ConvertValueToString(specificValueType, item));
|
||||
} else {
|
||||
writer.Write("{0}", ConvertValueToString(specificValueType, item));
|
||||
}
|
||||
}
|
||||
writer.WriteLine();
|
||||
} else if (valueType.IsGenericType && valueType.GetGenericTypeDefinition() == typeof(Dictionary<,>)) {
|
||||
// Handle dictionaries.
|
||||
Type valueType1 = valueType.GetGenericArguments()[0];
|
||||
Type valueType2 = valueType.GetGenericArguments()[1];
|
||||
// Get the methods we need to deal with dictionaries.
|
||||
var keys = valueType.GetProperty("Keys").GetValue(propertyValue, null);
|
||||
var item = valueType.GetProperty("Item");
|
||||
var enumerator = keys.GetType().GetMethod("GetEnumerator").Invoke(keys, null);
|
||||
var moveNext = enumerator.GetType().GetMethod("MoveNext");
|
||||
var current = enumerator.GetType().GetProperty("Current").GetGetMethod();
|
||||
// Get all the values.
|
||||
while ((bool)moveNext.Invoke(enumerator, null)) {
|
||||
var key = current.Invoke(enumerator, null);
|
||||
var valueObject = item.GetValue(propertyValue, new object[] { key });
|
||||
// Write to ini file!
|
||||
writer.WriteLine("{0}.{1}={2}", iniPropertyAttribute.Name, ConvertValueToString(valueType1, key), ConvertValueToString(valueType2, valueObject));
|
||||
}
|
||||
} else {
|
||||
writer.WriteLine("{0}={1}", iniPropertyAttribute.Name, ConvertValueToString(valueType, propertyValue));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
section.AfterSave();
|
||||
}
|
||||
}
|
||||
|
||||
private static void SaveInternally(string iniLocation) {
|
||||
WatchConfigFile(false);
|
||||
|
@ -694,7 +332,7 @@ namespace Greenshot.IniFile {
|
|||
}
|
||||
TextWriter writer = new StreamWriter(iniLocation, false, Encoding.UTF8);
|
||||
foreach (IniSection section in sectionMap.Values) {
|
||||
SaveIniSectionToWriter(writer, section, false);
|
||||
section.Write(writer, false);
|
||||
// Add empty line after section
|
||||
writer.WriteLine();
|
||||
section.IsDirty = false;
|
||||
|
|
|
@ -20,6 +20,8 @@
|
|||
*/
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using System.IO;
|
||||
|
||||
namespace Greenshot.IniFile {
|
||||
/// <summary>
|
||||
|
@ -27,16 +29,23 @@ namespace Greenshot.IniFile {
|
|||
/// </summary>
|
||||
[Serializable]
|
||||
public abstract class IniSection {
|
||||
protected static log4net.ILog LOG = log4net.LogManager.GetLogger(typeof(IniSection));
|
||||
|
||||
[NonSerialized]
|
||||
private IDictionary<string, IniValue> values = new Dictionary<string, IniValue>();
|
||||
|
||||
/// <summary>
|
||||
/// Get the dictionary with all the IniValues
|
||||
/// </summary>
|
||||
public IDictionary<string, IniValue> Values {
|
||||
get {
|
||||
return values;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Flag to specify if values have been changed
|
||||
/// </summary>
|
||||
public bool IsDirty = false;
|
||||
|
||||
/// <summary>
|
||||
|
@ -65,10 +74,86 @@ namespace Greenshot.IniFile {
|
|||
public virtual void AfterLoad() {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This will be called before saving the Section, so we can encrypt passwords etc...
|
||||
/// </summary>
|
||||
public virtual void BeforeSave() {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This will be called before saving the Section, so we can decrypt passwords etc...
|
||||
/// </summary>
|
||||
public virtual void AfterSave() {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Fill the section with the supplied properties
|
||||
/// </summary>
|
||||
/// <param name="properties"></param>
|
||||
public void Fill(Dictionary<string, string> properties) {
|
||||
Type iniSectionType = this.GetType();
|
||||
|
||||
// Iterate over the members and create IniValueContainers
|
||||
foreach (FieldInfo fieldInfo in iniSectionType.GetFields()) {
|
||||
if (Attribute.IsDefined(fieldInfo, typeof(IniPropertyAttribute))) {
|
||||
if (!Values.ContainsKey(fieldInfo.Name)) {
|
||||
IniPropertyAttribute iniPropertyAttribute = (IniPropertyAttribute)fieldInfo.GetCustomAttributes(typeof(IniPropertyAttribute), false)[0];
|
||||
Values.Add(fieldInfo.Name, new IniValue(this, fieldInfo, iniPropertyAttribute));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach (PropertyInfo propertyInfo in iniSectionType.GetProperties()) {
|
||||
if (Attribute.IsDefined(propertyInfo, typeof(IniPropertyAttribute))) {
|
||||
if (!Values.ContainsKey(propertyInfo.Name)) {
|
||||
IniPropertyAttribute iniPropertyAttribute = (IniPropertyAttribute)propertyInfo.GetCustomAttributes(typeof(IniPropertyAttribute), false)[0];
|
||||
Values.Add(propertyInfo.Name, new IniValue(this, propertyInfo, iniPropertyAttribute));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach (string fieldName in Values.Keys) {
|
||||
IniValue iniValue = Values[fieldName];
|
||||
try {
|
||||
iniValue.SetValueFromProperties(properties);
|
||||
} catch (Exception ex) {
|
||||
LOG.Error(ex);
|
||||
}
|
||||
}
|
||||
AfterLoad();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Write the section to the writer
|
||||
/// </summary>
|
||||
/// <param name="writer"></param>
|
||||
/// <param name="onlyProperties"></param>
|
||||
public void Write(TextWriter writer, bool onlyProperties) {
|
||||
BeforeSave();
|
||||
try {
|
||||
Attribute[] classAttributes = Attribute.GetCustomAttributes(this.GetType());
|
||||
IniSectionAttribute iniSectionAttribute = null;
|
||||
foreach (Attribute attribute in classAttributes) {
|
||||
if (attribute is IniSectionAttribute) {
|
||||
iniSectionAttribute = (IniSectionAttribute)attribute;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (iniSectionAttribute == null) {
|
||||
throw new ArgumentException("Section didn't implement the IniSectionAttribute");
|
||||
}
|
||||
|
||||
if (!onlyProperties) {
|
||||
writer.WriteLine("; {0}", iniSectionAttribute.Description);
|
||||
}
|
||||
writer.WriteLine("[{0}]", iniSectionAttribute.Name);
|
||||
|
||||
foreach (IniValue value in Values.Values) {
|
||||
value.Write(writer, onlyProperties);
|
||||
}
|
||||
} finally {
|
||||
AfterSave();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,25 +20,29 @@
|
|||
*/
|
||||
using System;
|
||||
using System.Reflection;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.IO;
|
||||
|
||||
namespace Greenshot.IniFile {
|
||||
/// <summary>
|
||||
/// A container to be able to pass the value from a IniSection around.
|
||||
/// </summary>
|
||||
public class IniValue {
|
||||
private static log4net.ILog LOG = log4net.LogManager.GetLogger(typeof(IniValue));
|
||||
private PropertyInfo propertyInfo;
|
||||
private FieldInfo fieldInfo;
|
||||
private object containingObject;
|
||||
private IniSection containingIniSection;
|
||||
private IniPropertyAttribute attributes;
|
||||
|
||||
public IniValue(object containingObject, PropertyInfo propertyInfo, IniPropertyAttribute iniPropertyAttribute) {
|
||||
this.containingObject = containingObject;
|
||||
public IniValue(IniSection containingIniSection, PropertyInfo propertyInfo, IniPropertyAttribute iniPropertyAttribute) {
|
||||
this.containingIniSection = containingIniSection;
|
||||
this.propertyInfo = propertyInfo;
|
||||
this.attributes = iniPropertyAttribute;
|
||||
}
|
||||
|
||||
public IniValue(object containingObject, FieldInfo fieldInfo, IniPropertyAttribute iniPropertyAttribute) {
|
||||
this.containingObject = containingObject;
|
||||
public IniValue(IniSection containingIniSection, FieldInfo fieldInfo, IniPropertyAttribute iniPropertyAttribute) {
|
||||
this.containingIniSection = containingIniSection;
|
||||
this.fieldInfo = fieldInfo;
|
||||
this.attributes = iniPropertyAttribute;
|
||||
}
|
||||
|
@ -52,6 +56,12 @@ namespace Greenshot.IniFile {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
public IniSection ContainingIniSection {
|
||||
get {
|
||||
return containingIniSection;
|
||||
}
|
||||
}
|
||||
|
||||
public IniPropertyAttribute Attributes {
|
||||
get {
|
||||
|
@ -62,28 +72,354 @@ namespace Greenshot.IniFile {
|
|||
public object Value {
|
||||
get {
|
||||
if (propertyInfo == null) {
|
||||
return fieldInfo.GetValue(containingObject);
|
||||
return fieldInfo.GetValue(containingIniSection);
|
||||
} else {
|
||||
return propertyInfo.GetValue(containingObject, null);
|
||||
return propertyInfo.GetValue(containingIniSection, null);
|
||||
}
|
||||
}
|
||||
set {
|
||||
if (propertyInfo == null) {
|
||||
fieldInfo.SetValue(containingObject, value);
|
||||
fieldInfo.SetValue(containingIniSection, value);
|
||||
} else {
|
||||
propertyInfo.SetValue(containingObject, value, null);
|
||||
propertyInfo.SetValue(containingIniSection, value, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Type ValueType {
|
||||
get {
|
||||
Type valueType = null;
|
||||
if (propertyInfo == null) {
|
||||
return fieldInfo.FieldType;
|
||||
valueType = fieldInfo.FieldType;
|
||||
} else {
|
||||
return propertyInfo.PropertyType;
|
||||
valueType = propertyInfo.PropertyType;
|
||||
}
|
||||
if (valueType.IsGenericType && valueType.GetGenericTypeDefinition().Equals(typeof(Nullable<>))) {
|
||||
// We are dealing with a generic type that is nullable
|
||||
valueType = Nullable.GetUnderlyingType(valueType);
|
||||
}
|
||||
return valueType;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Write the value to the text writer
|
||||
/// </summary>
|
||||
/// <param name="writer">TextWriter to write to</param>
|
||||
/// <param name="onlyProperties">true if we do not want the comment</param>
|
||||
public void Write(TextWriter writer, bool onlyProperties) {
|
||||
object myValue = Value;
|
||||
Type valueType = ValueType;
|
||||
if (myValue == null) {
|
||||
if (attributes.ExcludeIfNull) {
|
||||
return;
|
||||
}
|
||||
if (attributes.DefaultValue != null) {
|
||||
myValue = attributes.DefaultValue;
|
||||
valueType = typeof(string);
|
||||
} else {
|
||||
myValue = containingIniSection.GetDefault(attributes.Name);
|
||||
if (myValue != null) {
|
||||
valueType = myValue.GetType();
|
||||
}
|
||||
}
|
||||
}
|
||||
if (myValue == null) {
|
||||
if (attributes.ExcludeIfNull) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (!onlyProperties) {
|
||||
writer.WriteLine("; {0}", attributes.Description);
|
||||
}
|
||||
if (myValue == null) {
|
||||
writer.Write("{0}=", attributes.Name);
|
||||
return;
|
||||
}
|
||||
if (valueType.IsGenericType && valueType.GetGenericTypeDefinition() == typeof(List<>)) {
|
||||
Type specificValueType = valueType.GetGenericArguments()[0];
|
||||
writer.Write("{0}=", attributes.Name);
|
||||
int listCount = (int)valueType.GetProperty("Count").GetValue(myValue, null);
|
||||
// Loop though generic list
|
||||
for (int index = 0; index < listCount; index++) {
|
||||
object item = valueType.GetMethod("get_Item").Invoke(myValue, new object[] { index });
|
||||
|
||||
// Now you have an instance of the item in the generic list
|
||||
if (index < listCount - 1) {
|
||||
writer.Write("{0}" + attributes.Separator, ConvertValueToString(specificValueType, item));
|
||||
} else {
|
||||
writer.Write("{0}", ConvertValueToString(specificValueType, item));
|
||||
}
|
||||
}
|
||||
writer.WriteLine();
|
||||
} else if (valueType.IsGenericType && valueType.GetGenericTypeDefinition() == typeof(Dictionary<,>)) {
|
||||
// Handle dictionaries.
|
||||
Type valueType1 = valueType.GetGenericArguments()[0];
|
||||
Type valueType2 = valueType.GetGenericArguments()[1];
|
||||
// Get the methods we need to deal with dictionaries.
|
||||
var keys = valueType.GetProperty("Keys").GetValue(myValue, null);
|
||||
var item = valueType.GetProperty("Item");
|
||||
var enumerator = keys.GetType().GetMethod("GetEnumerator").Invoke(keys, null);
|
||||
var moveNext = enumerator.GetType().GetMethod("MoveNext");
|
||||
var current = enumerator.GetType().GetProperty("Current").GetGetMethod();
|
||||
// Get all the values.
|
||||
while ((bool)moveNext.Invoke(enumerator, null)) {
|
||||
var key = current.Invoke(enumerator, null);
|
||||
var valueObject = item.GetValue(myValue, new object[] { key });
|
||||
// Write to ini file!
|
||||
writer.WriteLine("{0}.{1}={2}", attributes.Name, ConvertValueToString(valueType1, key), ConvertValueToString(valueType2, valueObject));
|
||||
}
|
||||
} else {
|
||||
writer.WriteLine("{0}={1}", attributes.Name, ConvertValueToString(valueType, myValue));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set the value to the value in the ini file, or default
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public void SetValueFromProperties(Dictionary<string, string> properties) {
|
||||
string propertyName = attributes.Name;
|
||||
string defaultValue = attributes.DefaultValue;
|
||||
|
||||
// Get the value from the ini file, if there is none take the default
|
||||
if (!properties.ContainsKey(propertyName) && defaultValue != null) {
|
||||
// Mark as dirty, we didn't use properties from the file (even defaults from the default file are allowed)
|
||||
containingIniSection.IsDirty = true;
|
||||
//LOG.Debug("Passing default: " + propertyName + "=" + propertyDefaultValue);
|
||||
}
|
||||
|
||||
string propertyValue = null;
|
||||
if (properties.ContainsKey(propertyName) && properties[propertyName] != null) {
|
||||
propertyValue = containingIniSection.PreCheckValue(propertyName, properties[propertyName]);
|
||||
}
|
||||
UseValueOrDefault(propertyValue);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This method will set the ini value to the supplied value or use the default if non supplied
|
||||
/// </summary>
|
||||
/// <param name="propertyValue"></param>
|
||||
public void UseValueOrDefault(string propertyValue) {
|
||||
Type valueType = ValueType;
|
||||
string propertyName = attributes.Name;
|
||||
string defaultValue = attributes.DefaultValue;
|
||||
bool defaultUsed = false;
|
||||
object defaultValueFromConfig = containingIniSection.GetDefault(propertyName);
|
||||
|
||||
if (string.IsNullOrEmpty(propertyValue)) {
|
||||
if (defaultValue != null && defaultValue.Trim().Length != 0) {
|
||||
propertyValue = defaultValue;
|
||||
defaultUsed = true;
|
||||
} else if (defaultValueFromConfig != null) {
|
||||
LOG.DebugFormat("Default for Property {0} implemented!", propertyName);
|
||||
} else {
|
||||
if (attributes.ExcludeIfNull) {
|
||||
Value = null;
|
||||
return;
|
||||
}
|
||||
LOG.DebugFormat("Property {0} has no value or default value!", propertyName);
|
||||
}
|
||||
}
|
||||
// Now set the value
|
||||
if (valueType.IsGenericType && ValueType.GetGenericTypeDefinition() == typeof(List<>)) {
|
||||
string arraySeparator = attributes.Separator;
|
||||
object list = Activator.CreateInstance(ValueType);
|
||||
// Logic for List<>
|
||||
if (propertyValue == null) {
|
||||
if (defaultValueFromConfig != null) {
|
||||
Value = defaultValueFromConfig;
|
||||
return;
|
||||
}
|
||||
Value = list;
|
||||
return;
|
||||
}
|
||||
string[] arrayValues = propertyValue.Split(new string[] { arraySeparator }, StringSplitOptions.None);
|
||||
if (arrayValues == null || arrayValues.Length == 0) {
|
||||
Value = list;
|
||||
return;
|
||||
}
|
||||
bool addedElements = false;
|
||||
bool parseProblems = false;
|
||||
MethodInfo addMethodInfo = valueType.GetMethod("Add");
|
||||
|
||||
foreach (string arrayValue in arrayValues) {
|
||||
if (arrayValue != null && arrayValue.Length > 0) {
|
||||
object newValue = null;
|
||||
try {
|
||||
newValue = ConvertStringToValueType(valueType.GetGenericArguments()[0], arrayValue);
|
||||
} catch (Exception ex) {
|
||||
LOG.Warn(ex);
|
||||
//LOG.Error("Problem converting " + arrayValue + " to type " + fieldType.FullName, e);
|
||||
parseProblems = true;
|
||||
}
|
||||
if (newValue != null) {
|
||||
addMethodInfo.Invoke(list, new object[] { newValue });
|
||||
addedElements = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Try to fallback on a default
|
||||
if (!addedElements && parseProblems) {
|
||||
try {
|
||||
object fallbackValue = ConvertStringToValueType(valueType.GetGenericArguments()[0], defaultValue);
|
||||
addMethodInfo.Invoke(list, new object[] { fallbackValue });
|
||||
Value = list;
|
||||
return;
|
||||
} catch (Exception ex) {
|
||||
LOG.Warn(ex);
|
||||
//LOG.Error("Problem converting " + defaultValue + " to type " + fieldType.FullName, e);
|
||||
}
|
||||
}
|
||||
Value = list;
|
||||
return;
|
||||
} else if (valueType.IsGenericType && valueType.GetGenericTypeDefinition() == typeof(Dictionary<,>)) {
|
||||
// Logic for Dictionary<,>
|
||||
Type type1 = valueType.GetGenericArguments()[0];
|
||||
Type type2 = valueType.GetGenericArguments()[1];
|
||||
//LOG.Info(String.Format("Found Dictionary<{0},{1}>", type1.Name, type2.Name));
|
||||
object dictionary = Activator.CreateInstance(valueType);
|
||||
MethodInfo addMethodInfo = valueType.GetMethod("Add");
|
||||
bool addedElements = false;
|
||||
Dictionary<string, string> properties = IniConfig.PropertiesForSection(containingIniSection);
|
||||
foreach (string key in properties.Keys) {
|
||||
if (key != null && key.StartsWith(propertyName + ".")) {
|
||||
// What "key" do we need to store it under?
|
||||
string subPropertyName = key.Substring(propertyName.Length + 1);
|
||||
string stringValue = properties[key];
|
||||
object newValue1 = null;
|
||||
object newValue2 = null;
|
||||
try {
|
||||
newValue1 = ConvertStringToValueType(type1, subPropertyName);
|
||||
} catch (Exception ex) {
|
||||
LOG.Warn(ex);
|
||||
//LOG.Error("Problem converting " + subPropertyName + " to type " + type1.FullName, e);
|
||||
}
|
||||
try {
|
||||
newValue2 = ConvertStringToValueType(type2, stringValue);
|
||||
} catch (Exception ex) {
|
||||
LOG.Warn(ex);
|
||||
//LOG.Error("Problem converting " + stringValue + " to type " + type2.FullName, e);
|
||||
}
|
||||
addMethodInfo.Invoke(dictionary, new object[] { newValue1, newValue2 });
|
||||
addedElements = true;
|
||||
}
|
||||
}
|
||||
// No need to return something that isn't filled!
|
||||
if (addedElements) {
|
||||
Value = dictionary;
|
||||
return;
|
||||
} else if (defaultValueFromConfig != null) {
|
||||
Value = defaultValueFromConfig;
|
||||
return;
|
||||
}
|
||||
} if (defaultValueFromConfig != null) {
|
||||
Value = defaultValueFromConfig;
|
||||
return;
|
||||
} else {
|
||||
if (valueType.IsGenericType && valueType.GetGenericTypeDefinition().Equals(typeof(Nullable<>))) {
|
||||
// We are dealing with a generic type that is nullable
|
||||
valueType = Nullable.GetUnderlyingType(valueType);
|
||||
}
|
||||
object newValue = null;
|
||||
try {
|
||||
newValue = ConvertStringToValueType(valueType, propertyValue);
|
||||
} catch (Exception ex1) {
|
||||
newValue = null;
|
||||
if (!defaultUsed) {
|
||||
try {
|
||||
newValue = ConvertStringToValueType(valueType, defaultValue);
|
||||
} catch (Exception ex2) {
|
||||
LOG.Warn("Problem converting " + propertyValue + " to type " + valueType.FullName, ex2);
|
||||
}
|
||||
} else {
|
||||
LOG.Warn("Problem converting " + propertyValue + " to type " + valueType.FullName, ex1);
|
||||
}
|
||||
}
|
||||
Value = newValue;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Helper method for conversion
|
||||
/// </summary>
|
||||
/// <param name="valueType"></param>
|
||||
/// <param name="valueString"></param>
|
||||
/// <returns></returns>
|
||||
private static object ConvertStringToValueType(Type valueType, string valueString) {
|
||||
if (valueString == null) {
|
||||
return null;
|
||||
}
|
||||
if (valueType == typeof(string)) {
|
||||
return valueString;
|
||||
}
|
||||
TypeConverter converter = TypeDescriptor.GetConverter(valueType);
|
||||
//LOG.Debug("No convertor for " + fieldType.ToString());
|
||||
if (valueType == typeof(object) && valueString.Length > 0) {
|
||||
//LOG.Debug("Parsing: " + valueString);
|
||||
string[] values = valueString.Split(new Char[] { ':' });
|
||||
//LOG.Debug("Type: " + values[0]);
|
||||
//LOG.Debug("Value: " + values[1]);
|
||||
Type fieldTypeForValue = Type.GetType(values[0], true);
|
||||
//LOG.Debug("Type after GetType: " + fieldTypeForValue);
|
||||
return ConvertStringToValueType(fieldTypeForValue, values[1]);
|
||||
} else if (converter != null) {
|
||||
return converter.ConvertFromInvariantString(valueString);
|
||||
} else if (valueType.IsEnum) {
|
||||
if (valueString.Length > 0) {
|
||||
try {
|
||||
return Enum.Parse(valueType, valueString);
|
||||
} catch (ArgumentException ae) {
|
||||
//LOG.InfoFormat("Couldn't match {0} to {1}, trying case-insentive match", valueString, fieldType);
|
||||
foreach (Enum enumValue in Enum.GetValues(valueType)) {
|
||||
if (enumValue.ToString().Equals(valueString, StringComparison.InvariantCultureIgnoreCase)) {
|
||||
//LOG.Info("Match found...");
|
||||
return enumValue;
|
||||
}
|
||||
}
|
||||
throw ae;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static string ConvertValueToString(Type valueType, object valueObject) {
|
||||
if (valueObject == null) {
|
||||
// If there is nothing, deliver nothing!
|
||||
return "";
|
||||
}
|
||||
if (valueType == typeof(object)) {
|
||||
// object to String, this is the hardest
|
||||
// Format will be "FQTypename[,Assemblyname]:Value"
|
||||
|
||||
// Get the type so we can call ourselves recursive
|
||||
Type objectType = valueObject.GetType();
|
||||
|
||||
// Get the value as string
|
||||
string ourValue = ConvertValueToString(objectType, valueObject);
|
||||
|
||||
// Get the valuetype as string
|
||||
string valueTypeName = objectType.FullName;
|
||||
// Find the assembly name and only append it if it's not already in the fqtypename (like System.Drawing)
|
||||
string assemblyName = objectType.Assembly.FullName;
|
||||
// correct assemblyName, this also has version information etc.
|
||||
if (assemblyName.StartsWith("Green")) {
|
||||
assemblyName = assemblyName.Substring(0, assemblyName.IndexOf(','));
|
||||
}
|
||||
return String.Format("{0},{1}:{2}", valueTypeName, assemblyName, ourValue);
|
||||
} else {
|
||||
TypeConverter converter = TypeDescriptor.GetConverter(valueType);
|
||||
if (converter != null) {
|
||||
return converter.ConvertToInvariantString(valueObject);
|
||||
}
|
||||
}
|
||||
// All other types
|
||||
return valueObject.ToString();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue