StructLayoutAttribute
[StructLayout(LayoutKind.Explicit)] is another way to formulate an one-of type. Each field must have [FieldOffset(X)] attribute.
The first field at [FieldOffset(0)] indicates tag type. Its length and name can be anything. All other fields must have non zero offset. Note that referable types must be positioned at 8 byte alignments. (Avalanche.DataType.Net.dll)
[StructLayout(LayoutKind.Explicit)]
public struct OneOf
{
[FieldOffset(0)] public byte Tag;
[FieldOffset(1)] public int Integer;
[FieldOffset(1)] public short Short;
[FieldOffset(1)] public bool Bool;
}
enum is also suitable tag type.
[StructLayout(LayoutKind.Explicit)]
public struct OneOf2
{
[FieldOffset(0)] public Kind Tag;
[FieldOffset(1)] public int Integer;
[FieldOffset(1)] public short Short;
[FieldOffset(1)] public bool Bool;
public enum Kind : byte { UInt, Short, Bool }
}
Query
AccessorRequest(target) requests for IAccessor depending on type target.
// Create service
IService service = Services.Create(NetAccessorHandlers.Instance);
// Create container target
IContainerTarget target = new NetOneOf(typeof(OneOf));
// Create request
IRequestFor<IAccessor> request = new AccessorRequest(target);
// Issue request
IOneOfAccessor<OneOf> accessor = service.GetRequired<IRequest, IOneOfAccessor<OneOf>>(request);
OneOfAccessorRequest(target) requests for IOneOfAccessor<OneOf, Element>.
// Create service
IService service = Services.Create(NetAccessorHandlers.Instance);
// Create container target
IContainerTarget target = new NetOneOf(typeof(OneOf));
// Create request
IRequestFor<IOneOfAccessor> request = new OneOfAccessorRequest(target);
// Issue request
IOneOfAccessor<OneOf> accessor = service.GetRequired<IRequest, IOneOfAccessor<OneOf>>(request);
OneOfAccessorRequest is specifically a request for specific writers. Each can be assigned with explicit customization.
// Create service
IService service = Services.Create(NetAccessorHandlers.Instance);
// Create container target
IContainerTarget target = new NetOneOf(typeof(OneOf));
// Create request
IRequestFor<IOneOfAccessor> request = new OneOfAccessorRequest
{
Constructor = new ConstructorRequest(target),
Deconstructor = new DeconstructorRequest(target),
DefaultConstructor = new DefaultConstructorRequest(target),
Fields = new ContentAccessorsRequest(target),
IsAssigned = new IsAssignedRequest(target),
Unassign = new UnassignRequest(target),
ContainerType = new ContainerTypeRequest(target),
ContentType = new ContentTypeRequest(target),
};
// Issue request
IOneOfAccessor<OneOf> accessor = service.GetRequired<IRequest, IOneOfAccessor<OneOf>>(request);
Usage
.DefaultConstructor creates a oneof with default value.
OneOf oneOf = accessor.DefaultConstructor.Read();
.Constructor creates a oneof from enumerable of elements.
OneOf oneOf = accessor.Constructor.Read((0, (object)10));
.Deconstructor reads values as an enumerable.
OneOf oneOf = new OneOf { Tag = 0, Integer = 10 };
(int tag, object value) = accessor.Deconstructor.Read(ref oneOf);
.Fields contains one-of option types.
OneOf oneOf = default;
accessor.Fields[1].Writer.WriteAs<short, OneOf>(10, ref oneOf);
short value = accessor.Fields[1].Reader.ReadAs<OneOf, short>(oneOf);
.IsAssigned tests whether a oneof is assigned in container.
OneOf oneOf = new OneOf { Tag = 0, Integer = 10 };
bool nonNull = accessor.IsAssigned.Read(oneOf);
.Unassign removes oneof at container.
OneOf oneOf = new OneOf { Tag = 0, Integer = 10 };
accessor.Unassign.Write(default, ref oneOf);
Notes
Boxed value-types can be accessed as object.
// Create accessor
IOneOfAccessor<OneOf> accessor =
Services.Create(NetAccessorHandlers.Instance)
.GetRequiredService<IOneOfAccessor<OneOf>>();
// Create one-of in heap
object oneOf = new OneOf { Tag = 0, Integer = 10 };
// Assign case to box in heap
accessor.Fields[1].Writer.TypeCast<short, object>().Write((short)11, oneOf);
Full Example
Full example
using System.Runtime.InteropServices;
using Avalanche.Accessor;
using Avalanche.DataType;
using Avalanche.Service;
using Avalanche.Utilities;
using Avalanche.Writer;
using Microsoft.Extensions.DependencyInjection;
using static System.Console;
public class structlayoutattribute
{
public static void Run()
{
{
// <10>
// Create service
IService service = Services.Create(NetAccessorHandlers.Instance);
// Create container target
IContainerTarget target = new NetOneOf(typeof(OneOf));
// Create request
IRequestFor<IAccessor> request = new AccessorRequest(target);
// Issue request
IOneOfAccessor<OneOf> accessor = service.GetRequired<IRequest, IOneOfAccessor<OneOf>>(request);
// </10>
}
{
// <11>
// Create service
IService service = Services.Create(NetAccessorHandlers.Instance);
// Create container target
IContainerTarget target = new NetOneOf(typeof(OneOf));
// Create request
IRequestFor<IOneOfAccessor> request = new OneOfAccessorRequest(target);
// Issue request
IOneOfAccessor<OneOf> accessor = service.GetRequired<IRequest, IOneOfAccessor<OneOf>>(request);
// </11>
}
{
// <11B>
// Create service
IService service = Services.Create(NetAccessorHandlers.Instance);
// Create container target
IContainerTarget target = new NetOneOf(typeof(OneOf), typeof(object));
// Create request
IRequestFor<IOneOfAccessor> request = new OneOfAccessorRequest(target);
// Issue request
IOneOfAccessor<OneOf> accessor = service.GetRequired<IRequest, IOneOfAccessor<OneOf, object>>(request);
// </11B>
}
{
// <12>
// Create service
IService service = Services.Create(NetAccessorHandlers.Instance);
// Create container target
IContainerTarget target = new NetOneOf(typeof(OneOf));
// Create request
IRequestFor<IOneOfAccessor> request = new OneOfAccessorRequest
{
Constructor = new ConstructorRequest(target),
Deconstructor = new DeconstructorRequest(target),
DefaultConstructor = new DefaultConstructorRequest(target),
Fields = new ContentAccessorsRequest(target),
IsAssigned = new IsAssignedRequest(target),
Unassign = new UnassignRequest(target),
ContainerType = new ContainerTypeRequest(target),
ContentType = new ContentTypeRequest(target),
};
// Issue request
IOneOfAccessor<OneOf> accessor = service.GetRequired<IRequest, IOneOfAccessor<OneOf>>(request);
// </12>
}
{
IOneOfAccessor<OneOf, object> accessor = Services.Create(NetAccessorHandlers.Instance).GetRequiredService<IOneOfAccessor<OneOf, object>>();
{
// <51>
OneOf oneOf = accessor.DefaultConstructor.Read();
// </51>
}
{
// <52>
OneOf oneOf = accessor.Constructor.Read((0, (object)10));
// </52>
}
{
// <53>
OneOf oneOf = new OneOf { Tag = 0, Integer = 10 };
(int tag, object value) = accessor.Deconstructor.Read(ref oneOf);
// </53>
}
{
// <54>
OneOf oneOf = default;
accessor.Fields[1].Writer.WriteAs<short, OneOf>(10, ref oneOf);
short value = accessor.Fields[1].Reader.ReadAs<OneOf, short>(oneOf);
// </54>
}
{
// <62>
OneOf oneOf = new OneOf { Tag = 0, Integer = 10 };
bool nonNull = accessor.IsAssigned.Read(oneOf);
// </62>
}
{
// <63>
OneOf oneOf = new OneOf { Tag = 0, Integer = 10 };
accessor.Unassign.Write(default, ref oneOf);
// </63>
}
}
{
// <72>
// Create accessor
IOneOfAccessor<OneOf> accessor =
Services.Create(NetAccessorHandlers.Instance)
.GetRequiredService<IOneOfAccessor<OneOf>>();
// Create one-of in heap
object oneOf = new OneOf { Tag = 0, Integer = 10 };
// Assign case to box in heap
accessor.Fields[1].Writer.TypeCast<short, object>().Write((short)11, oneOf);
// </72>
}
}
// <100>
[StructLayout(LayoutKind.Explicit)]
public struct OneOf
{
[FieldOffset(0)] public byte Tag;
[FieldOffset(1)] public int Integer;
[FieldOffset(1)] public short Short;
[FieldOffset(1)] public bool Bool;
}
// </100>
// <101>
[StructLayout(LayoutKind.Explicit)]
public struct OneOf2
{
[FieldOffset(0)] public Kind Tag;
[FieldOffset(1)] public int Integer;
[FieldOffset(1)] public short Short;
[FieldOffset(1)] public bool Bool;
public enum Kind : byte { UInt, Short, Bool }
}
// </101>
}