using System;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
namespace OpenTap
{
/// Mixin member data
public class MixinMemberData : IMemberData, IDynamicMemberData
{
/// Attributes
public IEnumerable Attributes { get; set; } = Array.Empty();
/// Name of the member
public string Name { get; set; }
/// Declaring type. This should be the type of the target object.
public ITypeData DeclaringType { get; set; }
/// Describes the value of the member.
public ITypeData TypeDescriptor { get; set; }
/// If the member is writable.
public bool Writable { get; set; }
/// If the member is readable. This should generally be true.
public bool Readable { get; set; }
readonly ConditionalWeakTable dict = new ConditionalWeakTable();
readonly Func make;
/// Sets the value of the member.
public virtual void SetValue(object owner, object value)
{
dict.Remove(owner);
dict.GetValue(owner, owner => value);
}
/// Gets the value of the member.
public virtual object GetValue(object owner)
{
if (dict.TryGetValue(owner, out var value))
return value;
return DefaultValue;
}
/// The default value of the member.
public object DefaultValue { get; set; }
/// The object which was used to construct this.
public IMixinBuilder Source { get; }
internal object NewInstance()
{
if (DefaultValue != null) return DefaultValue;
if (TypeDescriptor.DescendsTo(typeof(string)))
return null;
if (make != null)
return make();
return TypeDescriptor.CreateInstance();
}
/// Creates a new instance of mixin member data.
public MixinMemberData(IMixinBuilder source, Func make = null)
{
this.make = make;
Writable = true;
Readable = true;
Source = source;
}
bool isDisposed = false;
bool IDynamicMemberData.IsDisposed => isDisposed;
// declare that this member data has been removed.
// this is important for parameterized mixin member data.
internal void Dispose()
{
isDisposed = true;
}
/// Creates a string representation of this mixin member data
public override string ToString()
{
return $"MixinMemberData: {Name}";
}
}
}