FieldReferer
Field referer is an IRefererBase<Record, Field> that returns pointer to a field.
IReferer<MyClass, int> myClassIdReferer;
IRefererFromRef<MyStruct, int> myStructIdReferer;
Creating a referer
A simple referer implements just IWriterToRef<record,Field>.
IReferer<MyClass, int> myClassIdReferer = new MyClassIdReferer();
IRefererFromRef<MyStruct, int> myStructIdReferer = new MyStructIdReferer();
/// <summary></summary>
public class MyClassIdReferer : IReferer<MyClass, int>
{
public bool CanRefer => true;
public Type FromType => typeof(MyClass);
public Type ToType => typeof(int);
public ref int GetReference(MyClass record, IServiceProvider? context = null) => ref record.Id;
public bool Accept(IWriterVisitorBase visitor) => visitor is not IRefererVisitor v ? true : v.Visit(refererT: this);
}
/// <summary></summary>
public class MyStructIdReferer : IRefererFromRef<MyStruct, int>
{
public bool CanRefer => true;
public Type FromType => typeof(MyStruct);
public Type ToType => typeof(int);
public ref int GetReference(ref MyStruct record, IServiceProvider? context = null) => ref record.Id;
public bool Accept(IWriterVisitorBase visitor) => visitor is not IRefererVisitor v ? true : v.Visit(refererTFR: this);
}
FieldRefererRequest(IFieldDescription) builds a referer from field description.
FieldInfo fi = typeof(MyClass).GetField("Id")!;
IFieldDescription fieldDescription = new FieldDescription().Read(fi).SetReadOnly();
FieldRefererRequest request = new FieldRefererRequest(fieldDescription);
IRefererBase<MyClass, int> myClassIdReferer = AccessorServices.Instance.GetRequired<FieldRefererRequest, IRefererBase<MyClass, int>>(request);
Usage
Referer get pointer to a field of a record.
MyClass myClass = new MyClass(6, "");
ref int id = ref myClassIdReferer.GetReference(myClass);
MyStruct myStruct = new MyStruct(7, "");
ref int id2 = ref myStructIdReferer.GetReference(ref myStruct);
Custom referer builder
Custom handler can front-run FieldRefererRequest request.
public class MyClassIdRefererBuilder : IHandler<FieldRefererRequest, IWriterBase>
{
[Order(-100)]
public void Handle(IQuery<FieldRefererRequest, IWriterBase> query)
{
// Already handled
if (query.Handled()) return;
//
if (query.Request.Target is not IFieldDescription fieldDescription) return;
// Get record type
Type recordType = fieldDescription.Record?.Type ?? (fieldDescription.Referer as MemberInfo)?.DeclaringType!;
// This handler only handles "MyClass"
if (!typeof(MyClass).Equals(recordType)) return;
//
if (!"Id".Equals(fieldDescription.Name?.ToString())) return;
// Create referer
IWriterBase referer = new MyClassIdReferer();
// Assign referer
query.Response.SetValue(referer);
}
}
// Create service
IService service = Services.Create((AccessorServices.Handlers, new MyClassIdRefererBuilder()), CachePolicies.Default);
// Create field description
IFieldDescription fieldDescription = new FieldDescription().Read(typeof(MyClass).GetField("Id")!).SetReadOnly();
// Referer request
FieldRefererRequest request = new FieldRefererRequest(fieldDescription);
// Get referer
IReferer<MyClass, int> myClassIdReferer = service.GetRequired<FieldRefererRequest, IReferer<MyClass, int>>(request);
// Create class
MyClass myClass = new MyClass(6, "");
// Read
ref int id = ref myClassIdReferer.GetReference(myClass);
Full Example
Full Example
Full example
using System;
using System.Reflection;
using Avalanche.Accessor;
using Avalanche.Service;
using Avalanche.Utilities;
using Avalanche.Utilities.Record;
using Avalanche.Writer;
public class fieldreferer
{
// <00>
public class MyClass
{
public int Id;
public string Label;
public MyClass(int id, string label)
{
Id = id;
Label = label;
}
}
public struct MyStruct
{
public int Id;
public string Label;
public MyStruct(int id, string label)
{
Id = id;
Label = label;
}
}
// </00>
public static void Run()
{
{
#pragma warning disable CS0168
// <01>
IReferer<MyClass, int> myClassIdReferer;
IRefererFromRef<MyStruct, int> myStructIdReferer;
// </01>
#pragma warning restore CS0168
}
{
// <11>
//var myClassIdReferer = DelegateWriter.Referer((MyClass record) => record.Id);
//var myStructIdReferer = DelegateWriter.Referer((MyStruct record) => record.Id);
// </11>
}
{
// <12>
IReferer<MyClass, int> myClassIdReferer = new MyClassIdReferer();
IRefererFromRef<MyStruct, int> myStructIdReferer = new MyStructIdReferer();
// </12>
}
{
// <17>
FieldInfo fi = typeof(MyClass).GetField("Id")!;
IFieldDescription fieldDescription = new FieldDescription().Read(fi).SetReadOnly();
FieldRefererRequest request = new FieldRefererRequest(fieldDescription);
IRefererBase<MyClass, int> myClassIdReferer = AccessorServices.Instance.GetRequired<FieldRefererRequest, IRefererBase<MyClass, int>>(request);
// </17>
}
{
FieldInfo fi = typeof(MyStruct).GetField("Id")!;
IFieldDescription myStructDescription = new FieldDescription().Read(fi).SetReadOnly();
FieldRefererRequest myStructRequest = new FieldRefererRequest(myStructDescription);
IRefererBase<MyStruct, int> myStructIdReferer = AccessorServices.Instance.GetRequired<FieldRefererRequest, IRefererBase<MyStruct, int>>(myStructRequest);
}
{
IReferer<MyClass, int> myClassIdReferer = new MyClassIdReferer();
IRefererFromRef<MyStruct, int> myStructIdReferer = new MyStructIdReferer();
// <21>
MyClass myClass = new MyClass(6, "");
ref int id = ref myClassIdReferer.GetReference(myClass);
MyStruct myStruct = new MyStruct(7, "");
ref int id2 = ref myStructIdReferer.GetReference(ref myStruct);
// </21>
}
{
// <32>
// Create service
IService service = Services.Create((AccessorServices.Handlers, new MyClassIdRefererBuilder()), CachePolicies.Default);
// Create field description
IFieldDescription fieldDescription = new FieldDescription().Read(typeof(MyClass).GetField("Id")!).SetReadOnly();
// Referer request
FieldRefererRequest request = new FieldRefererRequest(fieldDescription);
// Get referer
IReferer<MyClass, int> myClassIdReferer = service.GetRequired<FieldRefererRequest, IReferer<MyClass, int>>(request);
// Create class
MyClass myClass = new MyClass(6, "");
// Read
ref int id = ref myClassIdReferer.GetReference(myClass);
// </32>
}
}
// <13>
/// <summary></summary>
public class MyClassIdReferer : IReferer<MyClass, int>
{
public bool CanRefer => true;
public Type FromType => typeof(MyClass);
public Type ToType => typeof(int);
public ref int GetReference(MyClass record, IServiceProvider? context = null) => ref record.Id;
public bool Accept(IWriterVisitorBase visitor) => visitor is not IRefererVisitor v ? true : v.Visit(refererT: this);
}
/// <summary></summary>
public class MyStructIdReferer : IRefererFromRef<MyStruct, int>
{
public bool CanRefer => true;
public Type FromType => typeof(MyStruct);
public Type ToType => typeof(int);
public ref int GetReference(ref MyStruct record, IServiceProvider? context = null) => ref record.Id;
public bool Accept(IWriterVisitorBase visitor) => visitor is not IRefererVisitor v ? true : v.Visit(refererTFR: this);
}
// </13>
// <31>
public class MyClassIdRefererBuilder : IHandler<FieldRefererRequest, IWriterBase>
{
[Order(-100)]
public void Handle(IQuery<FieldRefererRequest, IWriterBase> query)
{
// Already handled
if (query.Handled()) return;
//
if (query.Request.Target is not IFieldDescription fieldDescription) return;
// Get record type
Type recordType = fieldDescription.Record?.Type ?? (fieldDescription.Referer as MemberInfo)?.DeclaringType!;
// This handler only handles "MyClass"
if (!typeof(MyClass).Equals(recordType)) return;
//
if (!"Id".Equals(fieldDescription.Name?.ToString())) return;
// Create referer
IWriterBase referer = new MyClassIdReferer();
// Assign referer
query.Response.SetValue(referer);
}
}
// </31>
}