IRecordAccessor from class
AccessorRequest<NetRecord> requests for record accessor of record-like class and struct types. (Avalanche.Accessor.Net.dll)
// Create container target
IContainerTarget target = new NetRecord(typeof(MyClass));
// Create request
AccessorRequest request = new AccessorRequest(target);
// Issue request
IRecordAccessor<MyClass> accessor =
Services.Create(NetAccessorHandlers.Instance)
.GetRequired<IRequest, IRecordAccessor<MyClass>>(request);
Sealed class is processed as Record if requested with NetType IContentTarget. If not sealed, then as Any.
public sealed record MyClass(int Id, string Label);
RecordAccessorRequest(Type) also requests for IRecordAccessor<T>.
// Create container target
IContainerTarget target = new NetRecord(typeof(MyClass));
// Create request
RecordAccessorRequest request = new RecordAccessorRequest(target);
// Issue request
IRecordAccessor<MyClass> accessor =
Services.Create(NetAccessorHandlers.Instance)
.GetRequired<RecordAccessorRequest, IRecordAccessor<MyClass>>(request);
Dependency injection request to IRecordAccessor<> is forwarded as RecordAccessorRequest.
IServiceProvider service = Services.Create(NetAccessorHandlers.Instance);
IRecordAccessor<MyClass> accessor = service.GetRequiredService<IRecordAccessor<MyClass>>();
IRecordDescription can be requested with NetRecord target.
// Create request
RecordDescriptionRequest request = new RecordDescriptionRequest(new NetRecord(typeof(MyClass)));
// Issue request
IRecordDescription description =
Services.Create(NetAccessorHandlers.Instance)
.GetRequired<RecordDescriptionRequest, IRecordDescription>(request);
Usage
.DefaultConstructor creates a record with default value.
MyClass record = accessor.DefaultConstructor.Read();
.Constructor creates a record from tuple.
MyClass record = accessor.Constructor.ReadAs<(int id, string label), MyClass>((10, "Hello"));
.Deconstructor reads values as an tuple.
MyClass record = new MyClass(10, "Hello");
(int id, string label) = accessor.Deconstructor.ReadAs<MyClass, (int id, string label)>(record);
.Fields contains record fields.
MyClass record = new MyClass(10, "Hello");
accessor.Fields[0].Writer.WriteAs<int, MyClass>(11, record);
int id = accessor.Fields[0].Reader.ReadAs<MyClass, int>(record);
.IsAssigned tests whether a record is assigned in container.
MyClass record = new MyClass(10, "Hello");
bool nonNull = accessor.IsAssigned.Read(record);
.Unassign removes record at container.
MyClass record = new MyClass(10, "Hello");
accessor.Unassign.Write(default, ref record);
public sealed record MyClass(int Id, string Label);
public record struct MyStruct(int Id, string Label);
Implementation
The default implementations work for most cases, however, more specific custom implementations can be crafted.
DefaultConstructor
Default constructor can be adapted from delegate.
var myClassDefaultConstructor = DelegateWriter.Reader<Avalanche.Void, MyClass>(@void => new MyClass(default, default));
var myStructDefaultConstructor = DelegateWriter.Reader<Avalanche.Void, MyStruct>(@void => new MyStruct(default, default));
Default constructor can be created with base class.
/// <summary></summary>
public class MyClassDefaultConstructor2 : RecordDefaultConstructorBaseClass<MyClass>
{
/// <summary></summary>
public override bool TryWrite(Avalanche.Void from, ref MyClass to, IServiceProvider? context = null)
{
to = new MyClass(default, default!);
return true;
}
}
/// <summary></summary>
public class MyStructDefaultConstructor2 : RecordDefaultConstructorBaseStruct<MyStruct>
{
/// <summary></summary>
public override bool TryWrite(Avalanche.Void from, ref MyStruct to, IServiceProvider? context = null)
{
to = new MyStruct(default, default!);
return true;
}
}
Handler processes DefaultConstructorRequest.
// Create service
IService service = Services.Create((NetAccessorHandlers.Instance, new MyClassDefaultConstructorBuilder()), CachePolicies.Default);
// Constructor request
DefaultConstructorRequest myClassRequest = new DefaultConstructorRequest(new NetRecord(typeof(MyClass)));
// Get constructor
IWriterToRef<Avalanche.Void, MyClass> myClassDefaultConstructor =
service.GetRequired<DefaultConstructorRequest, IWriterToRef<Avalanche.Void, MyClass>>(myClassRequest);
//
MyClass myClass = myClassDefaultConstructor.Read();
public class MyClassDefaultConstructorBuilder : IHandler<DefaultConstructorRequest, IWriter>
{
[Order(-100)]
public void Handle(IQuery<DefaultConstructorRequest, IWriter> query)
{
// Already handled
if (query.Handled()) return;
// Place type here
Type? recordType = null;
//
if (query.Request.Target is IConstructionDescription constructionDescription1)
{
recordType = constructionDescription1.Constructor?.Type ?? constructionDescription1.Constructor?.Record?.Type;
}
//
else if (query.Request.Target is IRecordDescription recordDescription1) recordType = recordDescription1?.Type;
//
else if (query.Request.Target 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 MyClassDefaultConstructor2());
}
}
Constructor
Constructor can be adapted from delegate.
var myClassDeconstructor = DelegateWriter.Reader<MyClass, (int, string)>(record => (record.Id, record.Label));
var myStructDeconstructor = DelegateWriter.Reader<MyStruct, (int, string)>(record => (record.Id, record.Label));
Constructor can be created with base class.
/// <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;
}
}
Handler processes ConstructorRequest.
// Create service
IService service = Services.Create((NetAccessorHandlers.Instance, new MyClassConstructorBuilder()), CachePolicies.Default);
// Constructor request
ConstructorRequest myClassRequest = new ConstructorRequest(new NetRecord(typeof(MyClass)));
// Get constructor
IWriterBase<(int, string), MyClass> myClassConstructor =
service.GetRequired<ConstructorRequest, IWriterBase<(int, string), MyClass>>(myClassRequest);
//
MyClass myClass = myClassConstructor.Read((15, "ZYX"));
public class MyClassConstructorBuilder : IHandler<ConstructorRequest, IWriter>
{
[Order(-100)]
public void Handle(IQuery<ConstructorRequest, IWriter> query)
{
// Already handled
if (query.Handled()) return;
// Place type here
Type? recordType = null;
// Get record type
if (query.Request.Target is IRecordDescription recordDescription1) recordType = recordDescription1?.Type;
else if (query.Request.Target is INetTarget netType1 && netType1.ContainerType is IRecordDescription recordDescription2) recordType = recordDescription2.Type;
else if (query.Request.Target is INetTarget netType2 && netType2.ContainerType 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 MyClassConstructor1());
}
}
Deconstructor
Deconstructor can be adapted from delegate.
var myClassDefaultConstructor = DelegateWriter.Reader<Avalanche.Void, MyClass>(@void => new MyClass(default, default));
var myStructDefaultConstructor = DelegateWriter.Reader<Avalanche.Void, MyStruct>(@void => new MyStruct(default, default));
Deconstructor can be created with base class.
/// <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;
}
}
Handler processes DeconstructorRequest.
// Create service
IService service = Services.Create((NetAccessorHandlers.Instance, new MyClassDeconstructorBuilder()), CachePolicies.Default);
// Constructor request
DeconstructorRequest myClassRequest = new DeconstructorRequest(new NetRecord(typeof(MyClass)));
// Get deconstructor
IWriterToRef<MyClass, (int, string)> myClassDeconstructor =
service.GetRequired<DeconstructorRequest, IWriterToRef<MyClass, (int, string)>>(myClassRequest);
//
(int, string) tuple = myClassDeconstructor.Read(new MyClass(80, "A"));
public class MyClassDeconstructorBuilder : IHandler<DeconstructorRequest, IWriter>
{
[Order(-100)]
public void Handle(IQuery<DeconstructorRequest, IWriter> query)
{
// Already handled
if (query.Handled()) return;
// Place type here
Type? recordType = null;
// Get record type
if (query.Request.Target is IRecordDescription recordDescription1) recordType = recordDescription1?.Type;
else if (query.Request.Target is INetTarget netType1 && netType1.ContainerType is IRecordDescription recordDescription2) recordType = recordDescription2.Type;
else if (query.Request.Target is INetTarget netType2 && netType2.ContainerType 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 MyClassDeconstructor1());
}
}
Full Example
Full example
using System;
using System.Linq;
using Avalanche.Accessor;
using Avalanche.DataType;
using Avalanche.Service;
using Avalanche.Utilities;
using Avalanche.Utilities.Record;
using Avalanche.Writer;
using Microsoft.Extensions.DependencyInjection;
public class @class
{
public static void Run()
{
{
// <10>
// Create container target
IContainerTarget target = new NetRecord(typeof(MyClass));
// Create request
AccessorRequest request = new AccessorRequest(target);
// Issue request
IRecordAccessor<MyClass> accessor =
Services.Create(NetAccessorHandlers.Instance)
.GetRequired<IRequest, IRecordAccessor<MyClass>>(request);
// </10>
}
{
// <11>
// Create container target
IContainerTarget target = new NetRecord(typeof(MyClass));
// Create request
RecordAccessorRequest request = new RecordAccessorRequest(target);
// Issue request
IRecordAccessor<MyClass> accessor =
Services.Create(NetAccessorHandlers.Instance)
.GetRequired<RecordAccessorRequest, IRecordAccessor<MyClass>>(request);
// </11>
}
{
// <12>
// Create request
RecordDescriptionRequest request = new RecordDescriptionRequest(new NetRecord(typeof(MyClass)));
// Issue request
IRecordDescription description =
Services.Create(NetAccessorHandlers.Instance)
.GetRequired<RecordDescriptionRequest, IRecordDescription>(request);
// </12>
}
{
// <14>
IServiceProvider service = Services.Create(NetAccessorHandlers.Instance);
IRecordAccessor<MyClass> accessor = service.GetRequiredService<IRecordAccessor<MyClass>>();
// </14>
}
{
// <15>
// Create request
RecordDescriptionRequest request = new RecordDescriptionRequest(new NetRecord(typeof(MyClass)));
// Issue request
IRecordDescription description =
Services.Create(NetAccessorHandlers.Instance)
.GetRequired<RecordDescriptionRequest, IRecordDescription>(request);
// </15>
}
/*
{
// <16>
// Create record
var record = new { Name = "User", Id = 100 };
// Issue request
IRecordAccessor accessor =
Services.Create(NetAccessorHandlers.Instance)
.GetRequired<IRequest, IRecordAccessor>(new AccessorRequest(new NetRecord(record.GetType())));
// Read name
string name = accessor.Fields[0].Reader.TypeCast<object, string>().Read(record);
// </16>
}
*/
{
IRecordAccessor<MyClass> accessor = Services.Create(NetAccessorHandlers.Instance).GetRequiredService<IRecordAccessor<MyClass>>();
{
// <51>
MyClass record = accessor.DefaultConstructor.Read();
// </51>
}
{
// <51E>
var myClassDefaultConstructor = DelegateWriter.Reader<Avalanche.Void, MyClass>(@void => new MyClass(default, default));
var myStructDefaultConstructor = DelegateWriter.Reader<Avalanche.Void, MyStruct>(@void => new MyStruct(default, default));
// </51E>
}
{
// <51H>
// Create service
IService service = Services.Create((NetAccessorHandlers.Instance, new MyClassDefaultConstructorBuilder()), CachePolicies.Default);
// Constructor request
DefaultConstructorRequest myClassRequest = new DefaultConstructorRequest(new NetRecord(typeof(MyClass)));
// Get constructor
IWriterToRef<Avalanche.Void, MyClass> myClassDefaultConstructor =
service.GetRequired<DefaultConstructorRequest, IWriterToRef<Avalanche.Void, MyClass>>(myClassRequest);
//
MyClass myClass = myClassDefaultConstructor.Read();
// </51H>
}
{
// <52>
MyClass record = accessor.Constructor.ReadAs<(int id, string label), MyClass>((10, "Hello"));
// </52>
}
{
// <52E>
var myClassDeconstructor = DelegateWriter.Reader<MyClass, (int, string)>(record => (record.Id, record.Label));
var myStructDeconstructor = DelegateWriter.Reader<MyStruct, (int, string)>(record => (record.Id, record.Label));
// </52E>
}
{
// <52H>
// Create service
IService service = Services.Create((NetAccessorHandlers.Instance, new MyClassConstructorBuilder()), CachePolicies.Default);
// Constructor request
ConstructorRequest myClassRequest = new ConstructorRequest(new NetRecord(typeof(MyClass)));
// Get constructor
IWriterBase<(int, string), MyClass> myClassConstructor =
service.GetRequired<ConstructorRequest, IWriterBase<(int, string), MyClass>>(myClassRequest);
//
MyClass myClass = myClassConstructor.Read((15, "ZYX"));
// </52H>
}
{
// <53>
MyClass record = new MyClass(10, "Hello");
(int id, string label) = accessor.Deconstructor.ReadAs<MyClass, (int id, string label)>(record);
// </53>
}
{
// <53E>
var myClassDefaultConstructor = DelegateWriter.Reader<Avalanche.Void, MyClass>(@void => new MyClass(default, default));
var myStructDefaultConstructor = DelegateWriter.Reader<Avalanche.Void, MyStruct>(@void => new MyStruct(default, default));
// </53E>
}
{
// <53H>
// Create service
IService service = Services.Create((NetAccessorHandlers.Instance, new MyClassDeconstructorBuilder()), CachePolicies.Default);
// Constructor request
DeconstructorRequest myClassRequest = new DeconstructorRequest(new NetRecord(typeof(MyClass)));
// Get deconstructor
IWriterToRef<MyClass, (int, string)> myClassDeconstructor =
service.GetRequired<DeconstructorRequest, IWriterToRef<MyClass, (int, string)>>(myClassRequest);
//
(int, string) tuple = myClassDeconstructor.Read(new MyClass(80, "A"));
// </53H>
}
{
// <54>
MyClass record = new MyClass(10, "Hello");
accessor.Fields[0].Writer.WriteAs<int, MyClass>(11, record);
int id = accessor.Fields[0].Reader.ReadAs<MyClass, int>(record);
// </54>
}
{
// <62>
MyClass record = new MyClass(10, "Hello");
bool nonNull = accessor.IsAssigned.Read(record);
// </62>
}
{
// <63>
MyClass record = new MyClass(10, "Hello");
accessor.Unassign.Write(default, ref record);
// </63>
}
}
}
// <51F>
/// <summary></summary>
public class MyClassDefaultConstructor2 : RecordDefaultConstructorBaseClass<MyClass>
{
/// <summary></summary>
public override bool TryWrite(Avalanche.Void from, ref MyClass to, IServiceProvider? context = null)
{
to = new MyClass(default, default!);
return true;
}
}
/// <summary></summary>
public class MyStructDefaultConstructor2 : RecordDefaultConstructorBaseStruct<MyStruct>
{
/// <summary></summary>
public override bool TryWrite(Avalanche.Void from, ref MyStruct to, IServiceProvider? context = null)
{
to = new MyStruct(default, default!);
return true;
}
}
// </51F>
// <51G>
public class MyClassDefaultConstructorBuilder : IHandler<DefaultConstructorRequest, IWriter>
{
[Order(-100)]
public void Handle(IQuery<DefaultConstructorRequest, IWriter> query)
{
// Already handled
if (query.Handled()) return;
// Place type here
Type? recordType = null;
//
if (query.Request.Target is IConstructionDescription constructionDescription1)
{
recordType = constructionDescription1.Constructor?.Type ?? constructionDescription1.Constructor?.Record?.Type;
}
//
else if (query.Request.Target is IRecordDescription recordDescription1) recordType = recordDescription1?.Type;
//
else if (query.Request.Target 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 MyClassDefaultConstructor2());
}
}
// </51G>
// <52F>
/// <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;
}
}
// </52F>
// <52G>
public class MyClassConstructorBuilder : IHandler<ConstructorRequest, IWriter>
{
[Order(-100)]
public void Handle(IQuery<ConstructorRequest, IWriter> query)
{
// Already handled
if (query.Handled()) return;
// Place type here
Type? recordType = null;
// Get record type
if (query.Request.Target is IRecordDescription recordDescription1) recordType = recordDescription1?.Type;
else if (query.Request.Target is INetTarget netType1 && netType1.ContainerType is IRecordDescription recordDescription2) recordType = recordDescription2.Type;
else if (query.Request.Target is INetTarget netType2 && netType2.ContainerType 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 MyClassConstructor1());
}
}
// </52G>
// <53F>
/// <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;
}
}
// </53F>
// <53G>
public class MyClassDeconstructorBuilder : IHandler<DeconstructorRequest, IWriter>
{
[Order(-100)]
public void Handle(IQuery<DeconstructorRequest, IWriter> query)
{
// Already handled
if (query.Handled()) return;
// Place type here
Type? recordType = null;
// Get record type
if (query.Request.Target is IRecordDescription recordDescription1) recordType = recordDescription1?.Type;
else if (query.Request.Target is INetTarget netType1 && netType1.ContainerType is IRecordDescription recordDescription2) recordType = recordDescription2.Type;
else if (query.Request.Target is INetTarget netType2 && netType2.ContainerType 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 MyClassDeconstructor1());
}
}
// </53G>
// <100>
public sealed record MyClass(int Id, string Label);
// </100>
// <101>
public record struct MyStruct(int Id, string Label);
// </101>
}