Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 3 additions & 5 deletions src/LLTSharp/LLTParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -703,23 +703,21 @@ private static void DeclareMainRules(ParserBuilder builder)

var obj = v.GetValue<TemplateDictionaryAccessor>(2);
var metadata = new List<IMetadata>();
var additionalMetadata = new AdditionalMetadata();

foreach (var pair in obj.Dictionary)
{
IMetadata? result = null;

foreach (var factory in factories)
if (factory.TryCreateMetadata(pair.Key, pair.Value, out result))
break;

if (result != null)
metadata.Add(result);
else
additionalMetadata.Set(pair.Key, pair.Value.GetValue());
metadata.Add(new AdditionalMetadata(pair.Key, pair.Value.GetValue()));
}

if (additionalMetadata.Count > 0)
metadata.Add(additionalMetadata.ToImmutable());

return new MetadataCollection(metadata);
});

Expand Down
2 changes: 1 addition & 1 deletion src/LLTSharp/LLTSharp.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

<PropertyGroup>
<PackageId>LLTSharp</PackageId>
<Version>1.2.4</Version>
<Version>1.3.0</Version>
<Authors>Roman K.</Authors>
<Company>RomeCore</Company>
<Product>LLTSharp</Product>
Expand Down
193 changes: 14 additions & 179 deletions src/LLTSharp/Metadata/AdditionalMetadata.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,208 +9,43 @@ namespace LLTSharp.Metadata
/// <summary>
/// Represents a dynamic metadata object that can store additional properties at runtime.
/// </summary>
public class AdditionalMetadata : DynamicObject, IAdditionalMetadata
public class AdditionalMetadata : IAdditionalMetadata, IEquatable<AdditionalMetadata>, IEquatable<IAdditionalMetadata>
{
private readonly Dictionary<string, object> _metadata = new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase);
public string Key { get; }

/// <summary>
/// Gets a shared immutable empty instance of additional metadata object.
/// </summary>
public static IAdditionalMetadata Empty => ImmutableAdditionalMetadata.Empty;

/// <summary>
/// Gets or sets the value associated with the specified key.
/// </summary>
/// <param name="key">The key of the value to get or set.</param>
/// <returns>The value associated with the specified key.</returns>
public object this[string key]
{
get => _metadata.TryGetValue(key, out var value) ? value : null;
set => _metadata[key] = value;
}

/// <summary>
/// Initializes a new instance of the <see cref="AdditionalMetadata"/> class.
/// </summary>
public AdditionalMetadata()
{
}
public object? Value { get; }

/// <summary>
/// Initializes a new instance of the <see cref="AdditionalMetadata"/> class with initial key-value pair.
/// </summary>
/// <param name="key">The key of the initial metadata item.</param>
/// <param name="value">The value of the initial metadata item.</param>
public AdditionalMetadata(string key, object value)
{
_metadata[key] = value;
}

/// <summary>
/// Initializes a new instance of the <see cref="AdditionalMetadata"/> class with dictionary of initial values.
/// </summary>
/// <param name="initialValues">Dictionary containing initial metadata values.</param>
public AdditionalMetadata(IDictionary<string, object> initialValues)
{
if (initialValues != null)
{
foreach (var kvp in initialValues)
{
_metadata[kvp.Key] = kvp.Value;
}
}
}

/// <summary>
/// Initializes a new instance of the <see cref="AdditionalMetadata"/> class with collection of key-value pairs.
/// </summary>
/// <param name="initialValues">Collection of key-value pairs for initial metadata.</param>
public AdditionalMetadata(IEnumerable<KeyValuePair<string, object>> initialValues)
{
if (initialValues != null)
{
foreach (var kvp in initialValues)
{
_metadata[kvp.Key] = kvp.Value;
}
}
}

/// <summary>
/// Gets the value associated with the specified key.
/// </summary>
/// <typeparam name="T">The type to convert the value to.</typeparam>
/// <param name="key">The key of the value to get.</param>
/// <returns>The converted value or default(T) if not found.</returns>
public T Get<T>(string key)
public AdditionalMetadata(string key, object? value)
{
if (_metadata.TryGetValue(key, out var value))
{
try
{
return (T)Convert.ChangeType(value, typeof(T));
}
catch
{
return default;
}
}
return default;
Key = key;
Value = value;
}

/// <summary>
/// Tries to get the value associated with the specified key.
/// </summary>
/// <typeparam name="T">The type to convert the value to.</typeparam>
/// <param name="key">The key of the value to get.</param>
/// <param name="value">When this method returns, contains the value if found; otherwise, default(T).</param>
/// <returns>true if the key was found; otherwise, false.</returns>
public bool TryGet<T>(string key, out T value)
{
if (_metadata.TryGetValue(key, out var objValue))
{
try
{
value = (T)Convert.ChangeType(objValue, typeof(T));
return true;
}
catch
{
value = default;
return false;
}
}
value = default;
return false;
}

/// <summary>
/// Adds or updates a metadata value.
/// </summary>
/// <param name="key">The key of the value to set.</param>
/// <param name="value">The value to set.</param>
public void Set(string key, object value)
{
_metadata[key] = value;
}

/// <summary>
/// Determines whether the metadata contains the specified key.
/// </summary>
/// <param name="key">The key to locate.</param>
/// <returns>true if the metadata contains the key; otherwise, false.</returns>
public bool ContainsKey(string key)
{
return _metadata.ContainsKey(key);
}

/// <summary>
/// Removes the value with the specified key.
/// </summary>
/// <param name="key">The key of the value to remove.</param>
/// <returns>true if the element was found and removed; otherwise, false.</returns>
public bool Remove(string key)
{
return _metadata.Remove(key);
}

/// <summary>
/// Gets all the keys in the metadata.
/// </summary>
public IEnumerable<string> Keys => _metadata.Keys;

/// <summary>
/// Gets all the values in the metadata.
/// </summary>
public IEnumerable<object> Values => _metadata.Values;

/// <summary>
/// Gets the number of metadata items.
/// </summary>
public int Count => _metadata.Count;

/// <summary>
/// Clears all metadata.
/// </summary>
public void Clear()
{
_metadata.Clear();
}

/// <summary>
/// Converts this instance to immutable copy.
/// </summary>
public ImmutableAdditionalMetadata ToImmutable()
{
return new ImmutableAdditionalMetadata(_metadata);
}

public override bool TryGetMember(GetMemberBinder binder, out object result)
{
return _metadata.TryGetValue(binder.Name, out result);
}

public override bool TrySetMember(SetMemberBinder binder, object value)
public override bool Equals(object? obj)
{
_metadata[binder.Name] = value;
return true;
return obj is AdditionalMetadata other && Equals(other);
}

public override IEnumerable<string> GetDynamicMemberNames()
public bool Equals(AdditionalMetadata? other)
{
return _metadata.Keys;
return other != null && Key == other.Key && Value == other.Value;
}

public override bool Equals(object? obj)
public bool Equals(IAdditionalMetadata? other)
{
return obj is AdditionalMetadata other &&
DictionaryUtils.DictionariesEqual(_metadata, other._metadata);
return other != null && Key == other.Key && Value == other.Value;
}

public override int GetHashCode()
{
int hash = 17;
hash = hash * 397 + DictionaryUtils.GetDictionaryHashCode(_metadata);
hash = hash * 397 + Key.GetHashCode();
hash = hash * 397 + (Value?.GetHashCode() ?? 0);
return hash;
}
}
Expand Down
19 changes: 6 additions & 13 deletions src/LLTSharp/Metadata/IAdditionalMetadata.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,25 +6,18 @@
namespace LLTSharp.Metadata
{
/// <summary>
/// Represents a dynamic metadata object that can store additional properties at runtime.
/// Represents a custom metadata object.
/// </summary>
public interface IAdditionalMetadata : IMetadata, IDynamicMetaObjectProvider
public interface IAdditionalMetadata : IMetadata
{
/// <summary>
/// Gets the value associated with the specified key.
/// Gets the key associated with this metadata.
/// </summary>
/// <typeparam name="T">The type to convert the value to.</typeparam>
/// <param name="key">The key of the value to get.</param>
/// <returns>The converted value or default(T) if not found.</returns>
T Get<T>(string key);
string Key { get; }

/// <summary>
/// Tries to get the value associated with the specified key.
/// Gets the value associated with this metadata.
/// </summary>
/// <typeparam name="T">The type to convert the value to.</typeparam>
/// <param name="key">The key of the value to get.</param>
/// <param name="value">When this method returns, contains the value if found; otherwise, default(T).</param>
/// <returns>true if the key was found; otherwise, false.</returns>
bool TryGet<T>(string key, out T value);
object? Value { get; }
}
}
Loading
Loading