RecordConstructor
Record constructor is an IWriterBase writer where 'from' type is a tuple represeting all the record's fields.
IWriterToRef<(int, string), MyClass> myClassConstructor;
IWriterToRef<(int, string), MyStruct> myStructConstructor;
Example class and struct.
public record MyClass(int Id, string Label);
public record struct MyStruct(int Id, string Label);
Creating a constructor
Constructor can be created with a delegate adapter.
var myClassConstructor = DelegateWriter.Reader<(int, string), MyClass>(tuple => new MyClass(tuple.Item1, tuple.Item2));
var myStructConstructor = DelegateWriter.Reader<(int, string), MyStruct>(tuple => new MyStruct(tuple.Item1, tuple.Item2));
Simple constructor implements just IWriterToRef<tT
/// <summary></summary>
public class MyClassConstructor1 : WriterToRef<(int, string), MyClass>
{
/// <summary></summary>
public override bool TryWrite((int, string) from, ref MyClass to, IServiceProvider? context = null)
{
to = new MyClass(from.Item1, from.Item2);
return true;
}
}
/// <summary></summary>
public class MyStructConstructor1 : WriterToRef<(int, string), MyStruct>
{
/// <summary></summary>
public override bool TryWrite((int, string) from, ref MyStruct to, IServiceProvider? context = null)
{
to = new MyStruct(from.Item1, from.Item2);
return true;
}
}
RecordConstructorBaseStruct and RecordConstructorBaseClass can be used for base class for constructor. Base class has more type-casting features.
IWriterToRef<(int, string), MyClass> myClassConstructor = new MyClassConstructor2();
IWriterToRef<(int, string), MyStruct> myStructConstructor = new MyStructConstructor2();
/// <summary></summary>
public class MyClassConstructor2 : RecordConstructorBaseClass<(int, string), MyClass>
{
/// <summary></summary>
public override bool TryWrite((int, string) from, ref MyClass to, IServiceProvider? context = null)
{
to = new MyClass(from.Item1, from.Item2);
return true;
}
}
/// <summary></summary>
public class MyStructConstructor2 : RecordConstructorBaseStruct<(int, string), MyStruct>
{
/// <summary></summary>
public override bool TryWrite((int, string) from, ref MyStruct to, IServiceProvider? context = null)
{
to = new MyStruct(from.Item1, from.Item2);
return true;
}
}
RecordConstructorRequest(Type) builds a constructor for record-like type using service stack's handlers.
RecordConstructorRequest myClassRequest = new RecordConstructorRequest(typeof(MyClass));
IWriterToRef<(int, string), MyClass> myClassConstructor = AccessorServices.Instance.GetRequired<RecordConstructorRequest, IWriterToRef<(int, string), MyClass>>(myClassRequest);
RecordConstructorRequest(IRecordDescription) builds a constructor from record description.
IRecordDescription myClassDescription = new RecordDescription().Read(typeof(MyClass)).AssignConstructors().ChooseConstruction().SetReadOnly();
RecordConstructorRequest myClassRequest = new RecordConstructorRequest(myClassDescription);
IWriterToRef<(int, string), MyClass> myClassConstructor = AccessorServices.Instance.GetRequired<RecordConstructorRequest, IWriterToRef<(int, string), MyClass>>(myClassRequest);
Usage
Constructor creates a record from a tuple value (int, string).
MyClass myClass = myClassConstructor.Read((5, "Hello"));
MyStruct myStruct = myStructConstructor.Read((5, "Hello"));
Constructor can be typecasted to e.g. IWriterBase<object, object>. Struct can be constructed right into a box in heap.
// Create tuple
(int, string) tuple = (0, "-");
// Copy tuple into a box
object tuplebox = tuple;
// Create box for result
object box = default(MyStruct);
// Write tuple into result in heap.
myStructConstructor.TypeCast<object, object>().WriteAs<object, object>(tuplebox, box);
Or a new box can be created.
// Read tuple and create new box for result.
object structBox2 = myStructConstructor.TypeCast<object, object>().ReadAs<object, object>(tuplebox);
Record can be constucted into ref pointer.
myStructConstructor.Write(tuple, ref myStruct);
Custom constructor builder
Custom handler can front-run RecordConstructorRequest.
public class MyClassConstructorBuilder : IHandler<RecordConstructorRequest, IWriterBase>
{
[Order(-100)]
public void Handle(IQuery<RecordConstructorRequest, IWriterBase> query)
{
// Already handled
if (query.Handled()) return;
// Place type here
Type? recordType = null;
//
if (query.Request.Record is IConstructionDescription constructionDescription1)
{
recordType = constructionDescription1.Constructor?.Type ?? constructionDescription1.Constructor?.Record?.Type;
}
//
else 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 MyClassConstructor2());
}
}
// Create service
IService service = Services.Create((AccessorServices.Handlers, new MyClassConstructorBuilder()), CachePolicies.Default);
// Constructor request
RecordConstructorRequest myClassRequest = new RecordConstructorRequest(typeof(MyClass));
// Get constructor
IWriterBase<(int, string), MyClass> myClassConstructor =
service.GetRequired<RecordConstructorRequest, IWriterBase<(int, string), MyClass>>(myClassRequest);
//
MyClass myClass = myClassConstructor.Read((15, "ZYX"));
Full Example
Full example
using System;
using Avalanche.Accessor;
using Avalanche.Service;
using Avalanche.Utilities;
using Avalanche.Utilities.Record;
using Avalanche.Writer;
public class recordconstructor
{
public static void Run()
{
{
#pragma warning disable CS0168
// <01>
IWriterToRef<(int, string), MyClass> myClassConstructor;
IWriterToRef<(int, string), MyStruct> myStructConstructor;
// </01>
#pragma warning restore CS0168
}
{
// <11>
var myClassConstructor = DelegateWriter.Reader<(int, string), MyClass>(tuple => new MyClass(tuple.Item1, tuple.Item2));
var myStructConstructor = DelegateWriter.Reader<(int, string), MyStruct>(tuple => new MyStruct(tuple.Item1, tuple.Item2));
// </11>
}
{
// <12>
IWriterToRef<(int, string), MyClass> myClassConstructor = new MyClassConstructor1();
IWriterToRef<(int, string), MyStruct> myStructConstructor = new MyStructConstructor1();
// </12>
}
{
// <14>
IWriterToRef<(int, string), MyClass> myClassConstructor = new MyClassConstructor2();
IWriterToRef<(int, string), MyStruct> myStructConstructor = new MyStructConstructor2();
// </14>
}
{
// <16>
RecordConstructorRequest myClassRequest = new RecordConstructorRequest(typeof(MyClass));
IWriterToRef<(int, string), MyClass> myClassConstructor = AccessorServices.Instance.GetRequired<RecordConstructorRequest, IWriterToRef<(int, string), MyClass>>(myClassRequest);
// </16>
RecordConstructorRequest myStructRequest = new RecordConstructorRequest(typeof(MyStruct));
IWriterToRef<(int, string), MyStruct> myStructConstructor = AccessorServices.Instance.GetRequired<RecordConstructorRequest, IWriterToRef<(int, string), MyStruct>>(myStructRequest);
}
{
// <17>
IRecordDescription myClassDescription = new RecordDescription().Read(typeof(MyClass)).AssignConstructors().ChooseConstruction().SetReadOnly();
RecordConstructorRequest myClassRequest = new RecordConstructorRequest(myClassDescription);
IWriterToRef<(int, string), MyClass> myClassConstructor = AccessorServices.Instance.GetRequired<RecordConstructorRequest, IWriterToRef<(int, string), MyClass>>(myClassRequest);
// </17>
IRecordDescription myStructDescription = new RecordDescription().Read(typeof(MyStruct)).AssignConstructors().ChooseConstruction().SetReadOnly();
RecordConstructorRequest myStructRequest = new RecordConstructorRequest(myStructDescription);
IWriterToRef<(int, string), MyStruct> myStructConstructor = AccessorServices.Instance.GetRequired<RecordConstructorRequest, IWriterToRef<(int, string), MyStruct>>(myStructRequest);
}
{
IWriterToRef<(int, string), MyClass> myClassConstructor = new MyClassConstructor2();
IWriterToRef<(int, string), MyStruct> myStructConstructor = new MyStructConstructor2();
// <21>
MyClass myClass = myClassConstructor.Read((5, "Hello"));
MyStruct myStruct = myStructConstructor.Read((5, "Hello"));
// </21>
// <22>
// Create tuple
(int, string) tuple = (0, "-");
// Copy tuple into a box
object tuplebox = tuple;
// Create box for result
object box = default(MyStruct);
// Write tuple into result in heap.
myStructConstructor.TypeCast<object, object>().WriteAs<object, object>(tuplebox, box);
// </22>
// <23>
// Read tuple and create new box for result.
object structBox2 = myStructConstructor.TypeCast<object, object>().ReadAs<object, object>(tuplebox);
// </23>
// <24>
myStructConstructor.Write(tuple, ref myStruct);
// </24>
}
{
// <32>
// Create service
IService service = Services.Create((AccessorServices.Handlers, new MyClassConstructorBuilder()), CachePolicies.Default);
// Constructor request
RecordConstructorRequest myClassRequest = new RecordConstructorRequest(typeof(MyClass));
// Get constructor
IWriterBase<(int, string), MyClass> myClassConstructor =
service.GetRequired<RecordConstructorRequest, IWriterBase<(int, string), MyClass>>(myClassRequest);
//
MyClass myClass = myClassConstructor.Read((15, "ZYX"));
// </32>
}
}
// <00>
public record MyClass(int Id, string Label);
public record struct MyStruct(int Id, string Label);
// </00>
// <13>
/// <summary></summary>
public class MyClassConstructor1 : WriterToRef<(int, string), MyClass>
{
/// <summary></summary>
public override bool TryWrite((int, string) from, ref MyClass to, IServiceProvider? context = null)
{
to = new MyClass(from.Item1, from.Item2);
return true;
}
}
/// <summary></summary>
public class MyStructConstructor1 : WriterToRef<(int, string), MyStruct>
{
/// <summary></summary>
public override bool TryWrite((int, string) from, ref MyStruct to, IServiceProvider? context = null)
{
to = new MyStruct(from.Item1, from.Item2);
return true;
}
}
// </13>
// <15>
/// <summary></summary>
public class MyClassConstructor2 : RecordConstructorBaseClass<(int, string), MyClass>
{
/// <summary></summary>
public override bool TryWrite((int, string) from, ref MyClass to, IServiceProvider? context = null)
{
to = new MyClass(from.Item1, from.Item2);
return true;
}
}
/// <summary></summary>
public class MyStructConstructor2 : RecordConstructorBaseStruct<(int, string), MyStruct>
{
/// <summary></summary>
public override bool TryWrite((int, string) from, ref MyStruct to, IServiceProvider? context = null)
{
to = new MyStruct(from.Item1, from.Item2);
return true;
}
}
// </15>
// <31>
public class MyClassConstructorBuilder : IHandler<RecordConstructorRequest, IWriterBase>
{
[Order(-100)]
public void Handle(IQuery<RecordConstructorRequest, IWriterBase> query)
{
// Already handled
if (query.Handled()) return;
// Place type here
Type? recordType = null;
//
if (query.Request.Record is IConstructionDescription constructionDescription1)
{
recordType = constructionDescription1.Constructor?.Type ?? constructionDescription1.Constructor?.Record?.Type;
}
//
else 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 MyClassConstructor2());
}
}
// </31>
}