priprava - v2
This commit is contained in:
@ -0,0 +1,34 @@
|
||||
using System;
|
||||
|
||||
namespace MadMilkman.Ini
|
||||
{
|
||||
/// <summary>
|
||||
/// Indicates the behavior of public property when serializing or deserializing the object that contains it.
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.Property, Inherited = false, AllowMultiple = false)]
|
||||
public sealed class IniSerializationAttribute : Attribute
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the <see cref="IniKey"/> name of serialized the property.
|
||||
/// </summary>
|
||||
public string Alias { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the value indicating whether serialization is ignored.
|
||||
/// </summary>
|
||||
public bool Ignore { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the IniSerializationAttribute class and specifies the <see cref="IniKey"/>'s name.
|
||||
/// </summary>
|
||||
/// <param name="alias">The name of the generated <see cref="IniKey"/>.</param>
|
||||
public IniSerializationAttribute(string alias) { this.Alias = alias; }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the IniSerializationAttribute class and specifies if serialization is ignored.
|
||||
/// </summary>
|
||||
/// <param name="ignore">The value indicating whether serialization is ignored.</param>
|
||||
public IniSerializationAttribute(bool ignore) { this.Ignore = ignore; }
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,128 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Reflection;
|
||||
|
||||
namespace MadMilkman.Ini
|
||||
{
|
||||
internal static class IniSerializer
|
||||
{
|
||||
private static readonly Predicate<Type> PropertyTypeVerifier = IniKey.IsSupportedValueType;
|
||||
|
||||
public static void Serialize<T>(T source, IniSection section) where T : class, new()
|
||||
{
|
||||
foreach (var propertyPair in GetPropertyPairs(typeof(T)))
|
||||
{
|
||||
var key = section.Keys.Add(propertyPair.Key);
|
||||
if (key.ParentCollectionCore != null)
|
||||
SetKeyValue(propertyPair.Value, source, key);
|
||||
}
|
||||
}
|
||||
|
||||
public static T Deserialize<T>(IniSection section) where T : class, new()
|
||||
{
|
||||
T destination = new T();
|
||||
|
||||
foreach (var propertyPair in GetPropertyPairs(typeof(T)))
|
||||
{
|
||||
var key = section.Keys[propertyPair.Key];
|
||||
if (key != null)
|
||||
SetPropertyValue(propertyPair.Value, destination, key);
|
||||
}
|
||||
|
||||
return destination;
|
||||
}
|
||||
|
||||
private static IEnumerable<KeyValuePair<string, PropertyInfo>> GetPropertyPairs(Type type)
|
||||
{
|
||||
foreach (var property in type.GetProperties(BindingFlags.Public | BindingFlags.Instance))
|
||||
{
|
||||
if (!IniSerializer.PropertyTypeVerifier(property.PropertyType))
|
||||
continue;
|
||||
|
||||
string propertyName = null;
|
||||
var attributes = property.GetCustomAttributes(typeof(IniSerializationAttribute), false);
|
||||
|
||||
if (attributes.Length > 0)
|
||||
{
|
||||
var attribute = (IniSerializationAttribute)attributes[0];
|
||||
if (attribute.Ignore)
|
||||
continue;
|
||||
|
||||
propertyName = attribute.Alias;
|
||||
}
|
||||
|
||||
yield return new KeyValuePair<string, PropertyInfo>((propertyName) ?? property.Name, property);
|
||||
}
|
||||
}
|
||||
|
||||
private static void SetKeyValue(PropertyInfo property, object source, IniKey key)
|
||||
{
|
||||
object propertyValue = property.GetValue(source, null);
|
||||
|
||||
if (propertyValue == null)
|
||||
return;
|
||||
|
||||
if (property.PropertyType.IsArray || property.PropertyType.GetInterface(typeof(IList).Name) != null)
|
||||
{
|
||||
var values = new List<string>();
|
||||
|
||||
/* MZ(2016-01-02): Fixed issue with null items in array and list. */
|
||||
foreach (var item in (IEnumerable)propertyValue)
|
||||
values.Add(item != null ? item.ToString() : null);
|
||||
|
||||
key.Values = values.ToArray();
|
||||
}
|
||||
else
|
||||
key.Value = propertyValue.ToString();
|
||||
}
|
||||
|
||||
private static void SetPropertyValue(PropertyInfo property, object destination, IniKey key)
|
||||
{
|
||||
var propertyType = property.PropertyType;
|
||||
|
||||
if (propertyType.IsArray)
|
||||
{
|
||||
/* MZ(2016-01-02): Fixed issue with null array and list. */
|
||||
if (!key.IsValueArray)
|
||||
return;
|
||||
|
||||
var values = key.Values;
|
||||
var itemType = propertyType.GetElementType();
|
||||
var array = Array.CreateInstance(itemType, values.Length);
|
||||
|
||||
for (int i = 0; i < values.Length; i++)
|
||||
array.SetValue(
|
||||
TypeDescriptor.GetConverter(itemType).ConvertFromInvariantString(values[i]),
|
||||
i);
|
||||
|
||||
property.SetValue(destination, array, null);
|
||||
}
|
||||
|
||||
else if (propertyType.GetInterface(typeof(IList).Name) != null)
|
||||
{
|
||||
/* MZ(2016-01-02): Fixed issue with null array and list. */
|
||||
if (!key.IsValueArray)
|
||||
return;
|
||||
|
||||
var itemType = propertyType.GetGenericArguments()[0];
|
||||
var list = (IList)Activator.CreateInstance(typeof(List<>).MakeGenericType(itemType));
|
||||
|
||||
var values = key.Values;
|
||||
if (!(values.Length == 1 && string.IsNullOrEmpty(values[0])))
|
||||
foreach (var value in values)
|
||||
list.Add(
|
||||
TypeDescriptor.GetConverter(itemType).ConvertFromInvariantString(value));
|
||||
|
||||
property.SetValue(destination, list, null);
|
||||
}
|
||||
|
||||
else
|
||||
property.SetValue(
|
||||
destination,
|
||||
TypeDescriptor.GetConverter(propertyType).ConvertFromInvariantString(key.Value),
|
||||
null);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,194 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Collections.Generic;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace MadMilkman.Ini
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a class that is used for binding operations, an operation in which the <see cref="IniKey">placeholder keys</see> values are replaced with an internal or external data.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para><see cref="IniValueBinding"/> can be accessed through <see cref="IniFile.ValueBinding"/> property.</para>
|
||||
/// <para>Binding can be executed with internal data source or with a provided external data source.</para>
|
||||
/// <para>For more information see <see href="c49dc3a5-866f-4d2d-8f89-db303aceb5fe.htm#binding" target="_self">IniKey's Value Binding</see>.</para>
|
||||
/// </remarks>
|
||||
/// <seealso href="c49dc3a5-866f-4d2d-8f89-db303aceb5fe.htm#binding" target="_self">IniKey's Value Binding</seealso>
|
||||
public sealed class IniValueBinding
|
||||
{
|
||||
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
|
||||
private readonly IniValueBindingEventArgs args;
|
||||
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
|
||||
private readonly IniFile iniFile;
|
||||
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
|
||||
private static readonly Regex placeholderPattern = new Regex(@"@\{[\w\s|]+\}", RegexOptions.Compiled | RegexOptions.CultureInvariant);
|
||||
|
||||
/// <summary>
|
||||
/// Occurs when a placeholder is binding with data source value and can be used to customize the binding operation.
|
||||
/// </summary>
|
||||
public event EventHandler<IniValueBindingEventArgs> Binding;
|
||||
|
||||
internal IniValueBinding(IniFile iniFile)
|
||||
{
|
||||
if (iniFile == null)
|
||||
throw new ArgumentNullException("iniFile");
|
||||
|
||||
this.iniFile = iniFile;
|
||||
this.args = new IniValueBindingEventArgs();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Executes a binding operation with internal data source.
|
||||
/// </summary>
|
||||
/// <seealso href="c49dc3a5-866f-4d2d-8f89-db303aceb5fe.htm#binding" target="_self">IniKey's Value Binding</seealso>
|
||||
public void Bind()
|
||||
{
|
||||
foreach (var placeholderPair in this.GetPlaceholderPairs(null))
|
||||
{
|
||||
IniKey placeholderKey = placeholderPair.Key;
|
||||
string placeholder = placeholderPair.Value;
|
||||
string placeholderName = placeholder.Substring(2, placeholder.Length - 3);
|
||||
string targetedValue;
|
||||
|
||||
int separator = placeholder.IndexOf('|');
|
||||
if (separator != -1)
|
||||
{
|
||||
var targetedSection = this.iniFile.Sections[placeholder.Substring(2, separator - 2)];
|
||||
if (targetedSection == null)
|
||||
continue;
|
||||
|
||||
targetedValue = GetTargetedValue(
|
||||
targetedSection,
|
||||
placeholder.Substring(separator + 1, placeholder.Length - separator - 2));
|
||||
}
|
||||
else
|
||||
targetedValue = GetTargetedValue(
|
||||
placeholderKey.ParentSection,
|
||||
placeholderName);
|
||||
|
||||
this.ExecuteBinding(placeholder, placeholderName, placeholderKey, targetedValue);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Executes a binding operation with external data source.
|
||||
/// </summary>
|
||||
/// <param name="dataSource">The binding data source.</param>
|
||||
/// <seealso href="c49dc3a5-866f-4d2d-8f89-db303aceb5fe.htm#binding" target="_self">IniKey's Value Binding</seealso>
|
||||
public void Bind(object dataSource) { this.Bind(dataSource, null); }
|
||||
|
||||
/// <summary>
|
||||
/// Executes a binding operation with external data source, only on specified section.
|
||||
/// </summary>
|
||||
/// <param name="dataSource">The binding data source.</param>
|
||||
/// <param name="sectionName">The <see cref="IniSection"/>'s name.</param>
|
||||
/// <seealso href="c49dc3a5-866f-4d2d-8f89-db303aceb5fe.htm#binding" target="_self">IniKey's Value Binding</seealso>
|
||||
public void Bind(object dataSource, string sectionName)
|
||||
{
|
||||
if (dataSource == null)
|
||||
throw new ArgumentNullException("dataSource");
|
||||
|
||||
var dataSourceDictionary = CreateDataSourceDictionary(dataSource);
|
||||
if (dataSourceDictionary == null)
|
||||
return;
|
||||
|
||||
foreach (var placeholderPair in this.GetPlaceholderPairs(this.iniFile.Sections[sectionName]))
|
||||
{
|
||||
IniKey placeholderKey = placeholderPair.Key;
|
||||
string placeholder = placeholderPair.Value;
|
||||
string placeholderName = placeholder.Substring(2, placeholder.Length - 3);
|
||||
string targetedValue;
|
||||
|
||||
dataSourceDictionary.TryGetValue(placeholderName, out targetedValue);
|
||||
|
||||
this.ExecuteBinding(placeholder, placeholderName, placeholderKey, targetedValue);
|
||||
}
|
||||
}
|
||||
|
||||
private void ExecuteBinding(string placeholder, string placeholderName, IniKey placeholderKey, string targetedValue)
|
||||
{
|
||||
this.args.Initialize(placeholderName, placeholderKey, targetedValue, targetedValue != null);
|
||||
|
||||
if (this.Binding != null)
|
||||
this.Binding(this, this.args);
|
||||
|
||||
if (this.args.Value != null)
|
||||
placeholderKey.Value = placeholderKey.Value.Replace(placeholder, this.args.Value);
|
||||
|
||||
this.args.Reset();
|
||||
}
|
||||
|
||||
// Returns placeholder pairs as KeyValuePair<IniKey, string>:
|
||||
// Key = IniKey in which value's the placeholder resides
|
||||
// Value = Placeholder, e.g. @{Placeholder}
|
||||
private IEnumerable<KeyValuePair<IniKey, string>> GetPlaceholderPairs(IniSection section)
|
||||
{
|
||||
if (section != null)
|
||||
{
|
||||
foreach (IniKey key in section.Keys)
|
||||
if (key.Value != null)
|
||||
{
|
||||
int matchStartat = key.Value.IndexOf("@{");
|
||||
if (matchStartat != -1)
|
||||
foreach (Match match in placeholderPattern.Matches(key.Value, matchStartat))
|
||||
yield return new KeyValuePair<IniKey, string>(key, match.Value);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (IniSection iniSection in this.iniFile.Sections)
|
||||
foreach (var placeholderPair in this.GetPlaceholderPairs(iniSection))
|
||||
yield return placeholderPair;
|
||||
}
|
||||
}
|
||||
|
||||
private static string GetTargetedValue(IniSection targetedSection, string targetedKeyName)
|
||||
{
|
||||
IniKey targetedKey = targetedSection.Keys[targetedKeyName];
|
||||
return targetedKey != null ? targetedKey.Value : null;
|
||||
}
|
||||
|
||||
/* REMARKS: TODO re-factor this, use providers ...
|
||||
*
|
||||
* CONSIDER: Implement support for any custom (including anonymous) types, use reflation ... */
|
||||
private static IDictionary<string, string> CreateDataSourceDictionary(object dataSource)
|
||||
{
|
||||
var dictionary = dataSource as IDictionary<string, string>;
|
||||
if (dictionary != null)
|
||||
return dictionary;
|
||||
|
||||
var collection = dataSource as ICollection<KeyValuePair<string, string>>;
|
||||
if (collection != null)
|
||||
{
|
||||
dictionary = new Dictionary<string, string>(collection.Count);
|
||||
|
||||
foreach (var dataSourceItem in collection)
|
||||
if (!dictionary.ContainsKey(dataSourceItem.Key))
|
||||
dictionary.Add(dataSourceItem);
|
||||
|
||||
return dictionary;
|
||||
}
|
||||
|
||||
var enumerator = dataSource as IEnumerable<KeyValuePair<string, string>>;
|
||||
if (enumerator != null)
|
||||
{
|
||||
dictionary = new Dictionary<string, string>();
|
||||
|
||||
foreach (var dataSourceItem in enumerator)
|
||||
if (!dictionary.ContainsKey(dataSourceItem.Key))
|
||||
dictionary.Add(dataSourceItem);
|
||||
|
||||
return dictionary;
|
||||
}
|
||||
|
||||
if (dataSource is KeyValuePair<string, string>)
|
||||
{
|
||||
dictionary = new Dictionary<string, string>(1);
|
||||
dictionary.Add((KeyValuePair<string, string>)dataSource);
|
||||
return dictionary;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,56 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace MadMilkman.Ini
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides data for <see cref="IniValueBinding.Binding"/> event.
|
||||
/// </summary>
|
||||
public sealed class IniValueBindingEventArgs : EventArgs
|
||||
{
|
||||
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
|
||||
private string placeholderName;
|
||||
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
|
||||
private IniKey placeholderKey;
|
||||
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
|
||||
private bool isValueFound;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the placeholder's name.
|
||||
/// </summary>
|
||||
public string PlaceholderName { get { return this.placeholderName; } }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the placeholder's <see cref="IniKey"/>.
|
||||
/// </summary>
|
||||
public IniKey PlaceholderKey { get { return this.placeholderKey; } }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the data source value that will replace the placeholder.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The data source value that will replace the placeholder, if it's not <see langword="null"/>.
|
||||
/// </value>
|
||||
public string Value { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether value was found in the data source.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// <see langword="true"/> if value was found in the data source.
|
||||
/// </value>
|
||||
public bool IsValueFound { get { return this.isValueFound; } }
|
||||
|
||||
internal IniValueBindingEventArgs() { }
|
||||
|
||||
internal void Initialize(string placeholderName, IniKey placeholderKey, string value, bool isValueFound)
|
||||
{
|
||||
this.placeholderName = placeholderName;
|
||||
this.placeholderKey = placeholderKey;
|
||||
this.Value = value;
|
||||
this.isValueFound = isValueFound;
|
||||
}
|
||||
|
||||
internal void Reset() { this.Initialize(null, null, null, false); }
|
||||
}
|
||||
}
|
@ -0,0 +1,77 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace MadMilkman.Ini
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a class of mapped <see cref="IniKey.Value"/>s and their results, used in <see cref="O:MadMilkman.Ini.IniKey.TryParseValue"/> methods.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para><see cref="IniValueMappings"/> can be accessed through <see cref="IniFile.ValueMappings"/> property.</para>
|
||||
/// <para>Mapped value results have priority over parsing the value.</para>
|
||||
/// <para>For more information see <see href="c49dc3a5-866f-4d2d-8f89-db303aceb5fe.htm#parsing" target="_self">IniKey's Value Parsing</see>.</para>
|
||||
/// </remarks>
|
||||
/// <seealso href="c49dc3a5-866f-4d2d-8f89-db303aceb5fe.htm#parsing" target="_self">IniKey's Value Parsing</seealso>
|
||||
public sealed class IniValueMappings
|
||||
{
|
||||
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
|
||||
private static readonly Predicate<Type> MappedTypeVerifier = IniKey.IsSupportedValueType;
|
||||
|
||||
private readonly IDictionary<string, object> mappings;
|
||||
|
||||
internal IniValueMappings() { this.mappings = new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase); }
|
||||
|
||||
/// <summary>
|
||||
/// Adds a new mapping of <see cref="IniKey.Value"/> to resulting object of parse methods.
|
||||
/// </summary>
|
||||
/// <param name="value">The key's value.</param>
|
||||
/// <param name="mappedResult">The object that represents parsed <see cref="IniKey.Value"/>.</param>
|
||||
/// <typeparam name="T">Type of the object that represents parsed <see cref="IniKey.Value"/>.</typeparam>
|
||||
/// <remarks>
|
||||
/// <para>The key's value cannot be <see langword="null"/>.</para>
|
||||
/// <para>The mapped result's type must be one of the supported types for parsing, see the remarks of <see cref="IniKey.IsSupportedValueType(Type)"/> method.</para>
|
||||
/// <para>Collection cannot contain multiple entries of same key's value, value comparison is case-insensitive.</para>
|
||||
/// </remarks>
|
||||
public void Add<T>(string value, T mappedResult)
|
||||
{
|
||||
if (value == null)
|
||||
throw new ArgumentNullException("value");
|
||||
|
||||
if (this.Contains(value) || !IniValueMappings.MappedTypeVerifier(typeof(T)))
|
||||
throw new InvalidOperationException();
|
||||
|
||||
this.mappings.Add(value, mappedResult);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether the collection contains a mapping for a specified key's value.
|
||||
/// </summary>
|
||||
/// <param name="value">The key's value to locate in the collection.</param>
|
||||
/// <returns><see langword="true"/> if the collection contains a mapping for a specified key's value.</returns>
|
||||
public bool Contains(string value) { return this.mappings.ContainsKey(value); }
|
||||
|
||||
/// <summary>
|
||||
/// Removes a mapping for a specified key's value in the collection.
|
||||
/// </summary>
|
||||
/// <param name="value">The key's value to remove in the collection.</param>
|
||||
/// <returns><see langword="true"/> if a mapping for a specified key's value is successfully found and removed.</returns>
|
||||
public bool Remove(string value) { return this.mappings.Remove(value); }
|
||||
|
||||
internal bool TryGetResult<T>(string value, out T result)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(value))
|
||||
{
|
||||
object mappedResult;
|
||||
if (this.mappings.TryGetValue(value, out mappedResult) &&
|
||||
mappedResult.GetType() == typeof(T))
|
||||
{
|
||||
result = (T)mappedResult;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
result = default(T);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,67 @@
|
||||
using System;
|
||||
|
||||
namespace MadMilkman.Ini
|
||||
{
|
||||
delegate bool TryParseDelegate<TDelegate>(string value, out TDelegate result);
|
||||
|
||||
internal static class IniValueParser<T>
|
||||
{
|
||||
private static TryParseDelegate<T> parser;
|
||||
|
||||
static IniValueParser() { InitializeParser(typeof(T)); }
|
||||
|
||||
private static void InitializeParser(Type type)
|
||||
{
|
||||
if (type.IsEnum) SetParser<T>(EnumTryParse);
|
||||
else if (type == typeof(TimeSpan)) SetParser<TimeSpan>(TimeSpan.TryParse);
|
||||
else
|
||||
switch (Type.GetTypeCode(type))
|
||||
{
|
||||
case TypeCode.Boolean: SetParser<bool>(bool.TryParse); break;
|
||||
case TypeCode.Byte: SetParser<byte>(byte.TryParse); break;
|
||||
case TypeCode.SByte: SetParser<sbyte>(sbyte.TryParse); break;
|
||||
case TypeCode.Int16: SetParser<short>(short.TryParse); break;
|
||||
case TypeCode.UInt16: SetParser<ushort>(ushort.TryParse); break;
|
||||
case TypeCode.Int32: SetParser<int>(int.TryParse); break;
|
||||
case TypeCode.UInt32: SetParser<uint>(uint.TryParse); break;
|
||||
case TypeCode.Int64: SetParser<long>(long.TryParse); break;
|
||||
case TypeCode.UInt64: SetParser<ulong>(ulong.TryParse); break;
|
||||
case TypeCode.Single: SetParser<float>(float.TryParse); break;
|
||||
case TypeCode.Double: SetParser<double>(double.TryParse); break;
|
||||
case TypeCode.Decimal: SetParser<decimal>(decimal.TryParse); break;
|
||||
case TypeCode.Char: SetParser<char>(char.TryParse); break;
|
||||
case TypeCode.DateTime: SetParser<DateTime>(DateTime.TryParse); break;
|
||||
case TypeCode.String: SetParser<string>((string value, out string result) => { result = value; return true; }); break;
|
||||
}
|
||||
}
|
||||
|
||||
private static void SetParser<TParser>(TryParseDelegate<TParser> parser)
|
||||
{
|
||||
IniValueParser<TParser>.parser = parser;
|
||||
}
|
||||
|
||||
private static bool EnumTryParse<TEnum>(string value, out TEnum result)
|
||||
{
|
||||
/* REMARKS: To support case insensitivity instead of Enum.IsDefined use Enum.GetNames
|
||||
* to achieve case insensitive string comparison between enum's names and value. */
|
||||
|
||||
Type type = typeof(TEnum);
|
||||
if (Enum.IsDefined((type), value))
|
||||
{
|
||||
result = (TEnum)Enum.Parse(type, value);
|
||||
return true;
|
||||
}
|
||||
|
||||
result = default(TEnum);
|
||||
return false;
|
||||
}
|
||||
|
||||
public static bool TryParse(string value, out T result)
|
||||
{
|
||||
if (parser == null)
|
||||
throw new NotSupportedException();
|
||||
|
||||
return parser(value, out result);
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user