Files
FSI.BT.IR.Tools/Config.Net/Core/InterfaceInterceptor.cs
Stephan Maier 647f938eee v1.2
2024-08-27 08:10:27 +02:00

104 lines
3.3 KiB
C#

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Reflection;
using System.Text;
using Castle.DynamicProxy;
using Config.Net.Core.Box;
namespace Config.Net.Core
{
class InterfaceInterceptor : IInterceptor
{
private readonly Dictionary<string, ResultBox> _boxes;
private IoHandler _ioHandler;
private readonly string? _prefix;
private readonly DynamicReader _reader;
private readonly DynamicWriter _writer;
private readonly bool _isInpc;
private PropertyChangedEventHandler? _inpcHandler;
public InterfaceInterceptor(Type interfaceType, IoHandler ioHandler, string? prefix = null)
{
_boxes = BoxFactory.Discover(interfaceType, ioHandler.ValueHandler, prefix);
_ioHandler = ioHandler;
_prefix = prefix;
_reader = new DynamicReader(prefix, ioHandler);
_writer = new DynamicWriter(prefix, ioHandler);
_isInpc = interfaceType.GetInterface(nameof(INotifyPropertyChanged)) != null;
}
private ResultBox FindBox(IInvocation invocation)
{
if (PropertyResultBox.IsProperty(invocation.Method, out string? propertyName) && propertyName != null)
{
return _boxes[propertyName];
}
else //method
{
string name = MethodResultBox.GetName(invocation.Method);
return _boxes[name];
}
}
public void Intercept(IInvocation invocation)
{
if (TryInterceptInpc(invocation)) return;
ResultBox rbox = FindBox(invocation);
bool isRead =
(rbox is PropertyResultBox && PropertyResultBox.IsGetProperty(invocation.Method)) ||
(rbox is ProxyResultBox && PropertyResultBox.IsGetProperty(invocation.Method)) ||
(rbox is MethodResultBox mbox && mbox.IsGettter) ||
(rbox is CollectionResultBox);
if(isRead)
{
invocation.ReturnValue = _reader.Read(rbox, -1, invocation.Arguments);
return;
}
else
{
_writer.Write(rbox, invocation.Arguments);
TryNotifyInpc(invocation, rbox);
}
}
private bool TryInterceptInpc(IInvocation invocation)
{
if (!_isInpc) return false;
if (invocation.Method.Name == "add_PropertyChanged")
{
invocation.ReturnValue =
_inpcHandler =
(PropertyChangedEventHandler)Delegate.Combine(_inpcHandler, (Delegate)invocation.Arguments[0]);
return true;
}
else if(invocation.Method.Name == "remove_PropertyChanged")
{
invocation.ReturnValue =
_inpcHandler =
(PropertyChangedEventHandler?)Delegate.Remove(_inpcHandler, (Delegate)invocation.Arguments[0]);
return true;
}
return false;
}
private void TryNotifyInpc(IInvocation invocation, ResultBox rbox)
{
if (_inpcHandler == null || rbox is MethodResultBox) return;
_inpcHandler.Invoke(invocation.InvocationTarget, new PropertyChangedEventArgs(rbox.Name));
if(rbox.Name != rbox.StoreByName)
{
//notify on StoreByName as well
_inpcHandler.Invoke(invocation.InvocationTarget, new PropertyChangedEventArgs(rbox.StoreByName));
}
}
}
}