diff --git a/mROA.Cbor/CborSerializationToolkit.cs b/mROA.Cbor/CborSerializationToolkit.cs index 6c50427..3fda2b2 100644 --- a/mROA.Cbor/CborSerializationToolkit.cs +++ b/mROA.Cbor/CborSerializationToolkit.cs @@ -183,7 +183,7 @@ namespace mROA.Cbor if (type == typeof(ulong)) return reader.ReadUInt64(); - return reader.ReadInt32(); + return reader.ReadUInt64(); case CborReaderState.ByteString: if (type == typeof(Guid)) return new Guid(reader.ReadByteString()); @@ -284,6 +284,7 @@ namespace mROA.Cbor private object ReadObject(CborReader reader, Type type, IEndPointContext? context) { + if (type == typeof(object)) { return new PreParsedValue(ReadList(reader, null, context) as List); @@ -311,12 +312,13 @@ namespace mROA.Cbor private void FillObject(object obj, Type type, CborReader reader, IEndPointContext? context) { + var propertyInfos = type.GetProperties(); + var properties = FilterProperties(propertyInfos); + + var length = reader.ReadStartArray(); try { - var propertyInfos = type.GetProperties(); - var properties = FilterProperties(propertyInfos); - var length = reader.ReadStartArray(); #if TRACE Console.WriteLine($"Reading list of {length} objects, {properties.Count} properties found"); #endif @@ -342,7 +344,7 @@ namespace mROA.Cbor public static List FilterProperties(PropertyInfo[] properties) { var finalProperties = new List(properties.Length); - foreach (var property in properties) + foreach (var property in properties.Where(i => i.CanWrite && i.CanRead)) { if (property.GetCustomAttribute() == null) finalProperties.Add(property); diff --git a/mROA.Cbor/PreParsedValue.cs b/mROA.Cbor/PreParsedValue.cs index e8e6379..5109c98 100644 --- a/mROA.Cbor/PreParsedValue.cs +++ b/mROA.Cbor/PreParsedValue.cs @@ -5,13 +5,18 @@ using mROA.Implementation; namespace mROA.Cbor { - public class PreParsedValue + public interface IPreParsedValue { - public List Properties { get; set; } + object? ToObject(Type type, IEndPointContext? context); + } + + public class PreParsedValue : IPreParsedValue + { + private List _properties { get; set; } public PreParsedValue(List properties) { - Properties = properties; + _properties = properties; } public object? ToObject(Type type, IEndPointContext? context) @@ -24,14 +29,31 @@ namespace mROA.Cbor { sharedObject.EndPointContext = context; } - + var properties = CborSerializationToolkit.FilterProperties(type.GetProperties()); for (var index = 0; index < properties.Count; index++) { var property = properties[index]; - property.SetValue(instance, Properties[index]); + property.SetValue(instance, _properties[index] is IPreParsedValue ppv ? ppv.ToObject(property.PropertyType, context) : _properties[index]); } + return instance; } } + + public class ParsedValue : IPreParsedValue + { + public ParsedValue(object? value) + { + _value = value; + } + + private object? _value; + + + public object? ToObject(Type type, IEndPointContext? context) + { + return _value; + } + } } \ No newline at end of file diff --git a/mROA/Implementation/Backend/ContextRepository.cs b/mROA/Implementation/Backend/ContextRepository.cs index 109c02a..65c4acf 100644 --- a/mROA/Implementation/Backend/ContextRepository.cs +++ b/mROA/Implementation/Backend/ContextRepository.cs @@ -60,7 +60,7 @@ namespace mROA.Implementation.Backend public T GetObjectBySharedObject(SharedObject sharedObject) { - return (T)GetObject(sharedObject.ContextId); + return (T)GetObject(sharedObject.Identifier.ContextId); } public object GetObject(int id) diff --git a/mROA/Implementation/Backend/MultiClientContextRepository.cs b/mROA/Implementation/Backend/MultiClientContextRepository.cs index d997ad2..e89be32 100644 --- a/mROA/Implementation/Backend/MultiClientContextRepository.cs +++ b/mROA/Implementation/Backend/MultiClientContextRepository.cs @@ -41,8 +41,8 @@ namespace mROA.Implementation.Backend public T GetObjectBySharedObject(SharedObject sharedObject) { - var repository = GetRepository(sharedObject.OwnerId); - return repository.GetObject(sharedObject.ContextId); + var repository = GetRepository(sharedObject.Identifier.OwnerId); + return repository.GetObject(sharedObject.Identifier.ContextId); } public object GetObject(int id) diff --git a/mROA/Implementation/RemoteContextRepository.cs b/mROA/Implementation/RemoteContextRepository.cs index 9fb7191..1990780 100644 --- a/mROA/Implementation/RemoteContextRepository.cs +++ b/mROA/Implementation/RemoteContextRepository.cs @@ -25,8 +25,8 @@ namespace mROA.Implementation throw new NullReferenceException("representation producer is not initialized"); if (!RemoteTypes.TryGetValue(typeof(T), out var remoteType)) throw new NotSupportedException(); - var representationModule = _representationProducer.Produce(sharedObject.OwnerId); - var remote = (T)Activator.CreateInstance(remoteType, sharedObject.ContextId, + var representationModule = _representationProducer.Produce(sharedObject.Identifier.OwnerId); + var remote = (T)Activator.CreateInstance(remoteType, sharedObject.Identifier.ContextId, representationModule)!; return remote; } diff --git a/mROA/Implementation/RemoteObjectBase.cs b/mROA/Implementation/RemoteObjectBase.cs index 535d5ba..b74b58a 100644 --- a/mROA/Implementation/RemoteObjectBase.cs +++ b/mROA/Implementation/RemoteObjectBase.cs @@ -21,7 +21,7 @@ namespace mROA.Implementation public int Id => _identifier.ContextId; public int OwnerId => _identifier.OwnerId; - + public UniversalObjectIdentifier Identifier => _identifier; protected async Task GetResultAsync(int methodId, object? parameter = default, CancellationToken cancellationToken = default) { diff --git a/mROA/Implementation/SharedObject.cs b/mROA/Implementation/SharedObject.cs index 67c97d9..1f8aae5 100644 --- a/mROA/Implementation/SharedObject.cs +++ b/mROA/Implementation/SharedObject.cs @@ -56,44 +56,58 @@ namespace mROA.Implementation }; private IContextRepository GetDefaultContextRepository() => - (OwnerId == EndPointContext.HostId + (_identifier.OwnerId == EndPointContext.HostId ? EndPointContext.RealRepository : EndPointContext.RemoteRepository) ?? throw new NullReferenceException( "DefaultContextRepository was not defined"); - private int _contextId = -2; - private int _ownerId = -1; + private UniversalObjectIdentifier _identifier = UniversalObjectIdentifier.Null; - public int OwnerId + public UniversalObjectIdentifier Identifier { get { - _ownerId = _ownerId == -1 ? EndPointContext.OwnerId : _ownerId; - return _ownerId; - } - set => _ownerId = value; - } - - // ReSharper disable once MemberCanBePrivate.Global - public int ContextId - { - // ReSharper disable once UnusedMember.Global - get - { - if (_contextId != -2) - return _contextId; - - _contextId = EndPointContext.RealRepository.GetObjectIndex(Value); - return _contextId; + _identifier.OwnerId = _identifier.OwnerId == -1 ? EndPointContext.OwnerId : _identifier.OwnerId; + return _identifier; } set { - _contextId = value; + _identifier = value; Value = GetDefaultContextRepository().GetObjectBySharedObject(this); } } + + // public int OwnerId + // { + // get + // { + // _ownerId = _ownerId == -1 ? EndPointContext.OwnerId : _ownerId; + // return _ownerId; + // } + // set => _ownerId = value; + // } + // + // // ReSharper disable once MemberCanBePrivate.Global + // public int ContextId + // { + // // ReSharper disable once UnusedMember.Global + // get + // { + // if (_contextId != -2) + // return _contextId; + // + // _contextId = EndPointContext.RealRepository.GetObjectIndex(Value); + // return _contextId; + // } + // set + // { + // _contextId = value; + // Value = GetDefaultContextRepository().GetObjectBySharedObject(this); + // } + // } + [JsonIgnore] [SerializationIgnore] public T Value { get; private set; } // ReSharper disable once MemberCanBePrivate.Global @@ -109,11 +123,13 @@ namespace mROA.Implementation if (value is RemoteObjectBase ro) { - _ownerId = ro.OwnerId; - _contextId = ro.Id; + _identifier = ro.Identifier; } else - _ownerId = EndPointContext.HostId; + { + _identifier.OwnerId = EndPointContext.HostId; + _identifier.ContextId = EndPointContext.RealRepository.GetObjectIndex(Value); + } } public static implicit operator T(SharedObject value) => value.Value; @@ -121,45 +137,4 @@ namespace mROA.Implementation public static implicit operator SharedObject(T value) => new(value); } - - public struct UniversalObjectIdentifier : IEquatable - { - public int ContextId; - public int OwnerId; - - public override string ToString() - { - return $"{nameof(ContextId)}: {ContextId}, {nameof(OwnerId)}: {OwnerId}"; - } - - public bool IsStatic => ContextId == -1; - - public ulong Flat - { - get - { - return (ulong)OwnerId << 32 | (uint)ContextId; - } - set - { - OwnerId = (int)(value >> 32); - ContextId = (int)(value & 0xFFFFFFFF); - } - } - - public bool Equals(UniversalObjectIdentifier other) - { - return ContextId == other.ContextId && OwnerId == other.OwnerId; - } - - public override bool Equals(object? obj) - { - return obj is UniversalObjectIdentifier other && Equals(other); - } - - public override int GetHashCode() - { - return HashCode.Combine(ContextId, OwnerId); - } - } } \ No newline at end of file diff --git a/mROA/Implementation/UniversalObjectIdentifier.cs b/mROA/Implementation/UniversalObjectIdentifier.cs new file mode 100644 index 0000000..445292f --- /dev/null +++ b/mROA/Implementation/UniversalObjectIdentifier.cs @@ -0,0 +1,47 @@ +using System; + +namespace mROA.Implementation +{ +#pragma warning disable CS8618, CS9264 + public struct UniversalObjectIdentifier : IEquatable + { + public int ContextId; + public int OwnerId; + + public static UniversalObjectIdentifier Null = new UniversalObjectIdentifier { ContextId = -2, OwnerId = -1 }; + public override string ToString() + { + return $"{{ {nameof(ContextId)}: {ContextId}, {nameof(OwnerId)}: {OwnerId} }}"; + } + + public bool IsStatic => ContextId == -1; + + public ulong Flat + { + get + { + return (ulong)OwnerId << 32 | (uint)ContextId; + } + set + { + OwnerId = (int)(value >> 32); + ContextId = (int)(value & 0xFFFFFFFF); + } + } + + public bool Equals(UniversalObjectIdentifier other) + { + return ContextId == other.ContextId && OwnerId == other.OwnerId; + } + + public override bool Equals(object? obj) + { + return obj is UniversalObjectIdentifier other && Equals(other); + } + + public override int GetHashCode() + { + return HashCode.Combine(ContextId, OwnerId); + } + } +} \ No newline at end of file