RecordDeconstructor
Record deconstructor extracts each field value into a tuple.
IWriterToRef<MyClass, (int, string)> myClassDeconstructor;
IWriterToRef<MyStruct, (int, string)> myStructDeconstructor;
Example class and struct.
public record MyClass(int Id, string Label);
public record struct MyStruct(int Id, string Label);
Creating a deconstructor
Deconstructor can be created with a delegate adapter.
var myClassDeconstructor = DelegateWriter.Reader<MyClass, (int, string)>(record => (record.Id, record.Label));
var myStructDeconstructor = DelegateWriter.Reader<MyStruct, (int, string)>(record => (record.Id, record.Label));
Simple deconstructor implements just IWriterToRef<Tuple,Record>.
IWriterToRef<MyClass, (int, string)> myClassDeconstructor = new MyClassDeconstructor1();
IWriterToRef<MyStruct, (int, string)> myStructDeconstructor = new MyStructDeconstructor1();
/// <summary></summary>
public class MyClassDeconstructor1 : WriterToRef<MyClass, (int, string)>
{
/// <summary></summary>
public override bool TryWrite(MyClass from, ref (int, string) to, IServiceProvider? context = null)
{
to.Item1 = from.Id;
to.Item2 = from.Label;
return true;
}
}
/// <summary></summary>
public class MyStructDeconstructor1 : WriterToRef<MyStruct, (int, string)>
{
/// <summary></summary>
public override bool TryWrite(MyStruct from, ref (int, string) to, IServiceProvider? context = null)
{
to.Item1 = from.Id;
to.Item2 = from.Label;
return true;
}
}
RecordDeconstructorBase can be used for base class for deconstructor. Base class has more type-casting features.
IWriterToRef<MyClass, (int, string)> myClassDeconstructor = new MyClassDeconstructor2();
IWriterToRef<MyStruct, (int, string)> myStructDeconstructor = new MyStructDeconstructor2();
/// <summary></summary>
public class MyClassDeconstructor2 : RecordDeconstructorBase<MyClass, (int, string)>
{
/// <summary></summary>
public override bool TryWrite(MyClass from, ref (int, string) to, IServiceProvider? context = null)
{
to.Item1 = from.Id;
to.Item2 = from.Label;
return true;
}
}
/// <summary></summary>
public class MyStructDeconstructor2 : RecordDeconstructorBase<MyStruct, (int, string)>
{
/// <summary></summary>
public override bool TryWrite(MyStruct from, ref (int, string) to, IServiceProvider? context = null)
{
to.Item1 = from.Id;
to.Item2 = from.Label;
return true;
}
}
RecordDeconstructorRequest(Type) builds a deconstructor for record-like types using service stack's handlers.
RecordDeconstructorRequest myClassRequest = new RecordDeconstructorRequest(typeof(MyClass));
RecordDeconstructorRequest myStructRequest = new RecordDeconstructorRequest(typeof(MyStruct));
IWriterToRef<MyClass, (int, string)> myClassDeconstructor = AccessorServices.Instance.GetRequired<RecordDeconstructorRequest, IWriterToRef<MyClass, (int, string)>>(myClassRequest);
IWriterToRef<MyStruct, (int, string)> myStructDeconstructor = AccessorServices.Instance.GetRequired<RecordDeconstructorRequest, IWriterToRef<MyStruct, (int, string)>>(myStructRequest);
RecordDeconstructorRequest(IRecordDescription) builds a deconstructor from record description.
IRecordDescription myClassDescription = new RecordDescription().Read(typeof(MyClass)).AssignConstructors().ChooseConstruction().SetReadOnly();
RecordDeconstructorRequest myClassRequest = new RecordDeconstructorRequest(myClassDescription);
IWriterToRef<MyClass, (int, string)> myClassDeconstructor = AccessorServices.Instance.GetRequired<RecordDeconstructorRequest, IWriterToRef<MyClass, (int, string)>>(myClassRequest);
Usage
Deconstructor creates tuple-value (int, string) from a record.
IWriterToRef<MyClass, (int, string)> myClassDeconstructor = new MyClassDeconstructor2();
IWriterToRef<MyStruct, (int, string)> myStructDeconstructor = new MyStructDeconstructor2();
Deconstructor can be typecasted to e.g. IWriterBase<object, object>. Tuple values can be written right into a box in heap.
MyClass myClass = new MyClass(5, "Hello");
(int, string) tuple1 = myClassDeconstructor.Read(myClass);
MyStruct myStruct = new MyStruct(5, "Hello");
(int, string) tuple2 = myClassDeconstructor.Read(myClass);
// Create record box
object box = myStruct;
// Read tuple box
object tupleBox = null!;
myStructDeconstructor.TypeCast<object, object>().WriteAs<object, object>(box, ref tupleBox);
Or a new box can be created.
tupleBox = myStructDeconstructor.TypeCast<object, object>().ReadAs<object, object>(box);
Custom deconstructor builder
Custom handler can front-run RecordDeconstructorRequest.
public class MyClassDeconstructorBuilder : IHandler<RecordDeconstructorRequest, IWriterBase>
{
[Order(-100)]
public void Handle(IQuery<RecordDeconstructorRequest, IWriterBase> query)
{
// Already handled
if (query.Handled()) return;
// Place type here
Type? recordType = null;
//
if (query.Request.Record is IRecordDescription recordDescription1) recordType = recordDescription1?.Type;
//
else if (query.Request.Record is Type type1) recordType = type1;
//
else return;
// This handler only handles "MyClass"
if (recordType == null || !recordType.Equals(typeof(MyClass))) return;
// Assign constructor
query.Response.SetValue(new MyClassDeconstructor2());
}
}
// Create service
IService service = Services.Create((AccessorServices.Handlers, new MyClassDeconstructorBuilder()), CachePolicies.Default);
// Constructor request
RecordDeconstructorRequest myClassRequest = new RecordDeconstructorRequest(typeof(MyClass));
// Get deconstructor
IWriterToRef<MyClass, (int, string)> myClassDeconstructor =
service.GetRequired<RecordDeconstructorRequest, IWriterToRef<MyClass, (int, string)>>(myClassRequest);
//
(int, string) tuple = myClassDeconstructor.Read(new MyClass(80, "A"));
Full Example
Full example
using System;
using Avalanche.Accessor;
using Avalanche.Service;
using Avalanche.Utilities;
using Avalanche.Utilities.Record;
using Avalanche.Writer;
public class recorddeconstructor
{
public static void Run()
{
{
#pragma warning disable CS0168
// <01>
IWriterToRef<MyClass, (int, string)> myClassDeconstructor;
IWriterToRef<MyStruct, (int, string)> myStructDeconstructor;
// </01>
#pragma warning restore CS0168
}
{
// <11>
var myClassDeconstructor = DelegateWriter.Reader<MyClass, (int, string)>(record => (record.Id, record.Label));
var myStructDeconstructor = DelegateWriter.Reader<MyStruct, (int, string)>(record => (record.Id, record.Label));
// </11>
}
{
// <12>
IWriterToRef<MyClass, (int, string)> myClassDeconstructor = new MyClassDeconstructor1();
IWriterToRef<MyStruct, (int, string)> myStructDeconstructor = new MyStructDeconstructor1();
// </12>
}
{
// <14>
IWriterToRef<MyClass, (int, string)> myClassDeconstructor = new MyClassDeconstructor2();
IWriterToRef<MyStruct, (int, string)> myStructDeconstructor = new MyStructDeconstructor2();
// </14>
}
{
// <16>
RecordDeconstructorRequest myClassRequest = new RecordDeconstructorRequest(typeof(MyClass));
RecordDeconstructorRequest myStructRequest = new RecordDeconstructorRequest(typeof(MyStruct));
IWriterToRef<MyClass, (int, string)> myClassDeconstructor = AccessorServices.Instance.GetRequired<RecordDeconstructorRequest, IWriterToRef<MyClass, (int, string)>>(myClassRequest);
IWriterToRef<MyStruct, (int, string)> myStructDeconstructor = AccessorServices.Instance.GetRequired<RecordDeconstructorRequest, IWriterToRef<MyStruct, (int, string)>>(myStructRequest);
// </16>
}
{
// <17>
IRecordDescription myClassDescription = new RecordDescription().Read(typeof(MyClass)).AssignConstructors().ChooseConstruction().SetReadOnly();
RecordDeconstructorRequest myClassRequest = new RecordDeconstructorRequest(myClassDescription);
IWriterToRef<MyClass, (int, string)> myClassDeconstructor = AccessorServices.Instance.GetRequired<RecordDeconstructorRequest, IWriterToRef<MyClass, (int, string)>>(myClassRequest);
// </17>
IRecordDescription myStructDescription = new RecordDescription().Read(typeof(MyStruct)).AssignConstructors().ChooseConstruction().SetReadOnly();
RecordDeconstructorRequest myStructRequest = new RecordDeconstructorRequest(myStructDescription);
IWriterToRef<MyStruct, (int, string)> myStructDeconstructor = AccessorServices.Instance.GetRequired<RecordDeconstructorRequest, IWriterToRef<MyStruct, (int, string)>>(myStructRequest);
}
{
// <21>
IWriterToRef<MyClass, (int, string)> myClassDeconstructor = new MyClassDeconstructor2();
IWriterToRef<MyStruct, (int, string)> myStructDeconstructor = new MyStructDeconstructor2();
// </21>
// <22>
MyClass myClass = new MyClass(5, "Hello");
(int, string) tuple1 = myClassDeconstructor.Read(myClass);
MyStruct myStruct = new MyStruct(5, "Hello");
(int, string) tuple2 = myClassDeconstructor.Read(myClass);
// Create record box
object box = myStruct;
// Read tuple box
object tupleBox = null!;
myStructDeconstructor.TypeCast<object, object>().WriteAs<object, object>(box, ref tupleBox);
// </22>
// <23>
tupleBox = myStructDeconstructor.TypeCast<object, object>().ReadAs<object, object>(box);
// </23>
}
{
// <32>
// Create service
IService service = Services.Create((AccessorServices.Handlers, new MyClassDeconstructorBuilder()), CachePolicies.Default);
// Constructor request
RecordDeconstructorRequest myClassRequest = new RecordDeconstructorRequest(typeof(MyClass));
// Get deconstructor
IWriterToRef<MyClass, (int, string)> myClassDeconstructor =
service.GetRequired<RecordDeconstructorRequest, IWriterToRef<MyClass, (int, string)>>(myClassRequest);
//
(int, string) tuple = myClassDeconstructor.Read(new MyClass(80, "A"));
// </32>
}
}
// <00>
public record MyClass(int Id, string Label);
public record struct MyStruct(int Id, string Label);
// </00>
// <13>
/// <summary></summary>
public class MyClassDeconstructor1 : WriterToRef<MyClass, (int, string)>
{
/// <summary></summary>
public override bool TryWrite(MyClass from, ref (int, string) to, IServiceProvider? context = null)
{
to.Item1 = from.Id;
to.Item2 = from.Label;
return true;
}
}
/// <summary></summary>
public class MyStructDeconstructor1 : WriterToRef<MyStruct, (int, string)>
{
/// <summary></summary>
public override bool TryWrite(MyStruct from, ref (int, string) to, IServiceProvider? context = null)
{
to.Item1 = from.Id;
to.Item2 = from.Label;
return true;
}
}
// </13>
// <15>
/// <summary></summary>
public class MyClassDeconstructor2 : RecordDeconstructorBase<MyClass, (int, string)>
{
/// <summary></summary>
public override bool TryWrite(MyClass from, ref (int, string) to, IServiceProvider? context = null)
{
to.Item1 = from.Id;
to.Item2 = from.Label;
return true;
}
}
/// <summary></summary>
public class MyStructDeconstructor2 : RecordDeconstructorBase<MyStruct, (int, string)>
{
/// <summary></summary>
public override bool TryWrite(MyStruct from, ref (int, string) to, IServiceProvider? context = null)
{
to.Item1 = from.Id;
to.Item2 = from.Label;
return true;
}
}
// </15>
// <31>
public class MyClassDeconstructorBuilder : IHandler<RecordDeconstructorRequest, IWriterBase>
{
[Order(-100)]
public void Handle(IQuery<RecordDeconstructorRequest, IWriterBase> query)
{
// Already handled
if (query.Handled()) return;
// Place type here
Type? recordType = null;
//
if (query.Request.Record is IRecordDescription recordDescription1) recordType = recordDescription1?.Type;
//
else if (query.Request.Record is Type type1) recordType = type1;
//
else return;
// This handler only handles "MyClass"
if (recordType == null || !recordType.Equals(typeof(MyClass))) return;
// Assign constructor
query.Response.SetValue(new MyClassDeconstructor2());
}
}
// </31>
}