Skip to content

Commit

Permalink
deprecate IEventInvoker
Browse files Browse the repository at this point in the history
  • Loading branch information
smdn committed Nov 15, 2024
1 parent 9e606a1 commit c296d61
Show file tree
Hide file tree
Showing 13 changed files with 127 additions and 139 deletions.
89 changes: 89 additions & 0 deletions src/Common/Smdn.Net.EchonetLite.ComponentModel/EventInvoker.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
// SPDX-FileCopyrightText: 2024 smdn <smdn@smdn.jp>
// SPDX-License-Identifier: MIT
using System;
using System.ComponentModel;

namespace Smdn.Net.EchonetLite.ComponentModel;

internal static class EventInvoker {
/// <summary>
/// イベントハンドラーの呼び出しを行い、イベントを発生させます。
/// 必要に応じて<see cref="ISynchronizeInvoke"/>によるイベントハンドラー呼び出しのマーシャリングを行います。
/// </summary>
/// <typeparam name="TEventArgs"><see cref="EventHandler{TEventArgs}"/>型のイベントハンドラーで使用されるイベント引数の型。</typeparam>
/// <param name="synchronizingObject">イベントハンドラーの呼び出しに使用する<see cref="ISynchronizeInvoke"/>。</param>
/// <param name="sender">イベントのソース。</param>
/// <param name="eventHandler">発生させるイベントのイベントハンドラー。</param>
/// <param name="e">発生させるイベントのイベント引数。</param>
// `RaiseEvent` cannot be used to name this method.
public static void Invoke<TEventArgs>(
ISynchronizeInvoke? synchronizingObject,
object? sender,
EventHandler<TEventArgs>? eventHandler,
TEventArgs e
) where TEventArgs : EventArgs
=> Invoke<EventHandler<TEventArgs>, TEventArgs>(
synchronizingObject: synchronizingObject,
sender: sender,
eventHandler: eventHandler,
e: e
);

/// <summary>
/// イベントハンドラーの呼び出しを行い、イベントを発生させます。
/// 必要に応じて<see cref="ISynchronizeInvoke"/>によるイベントハンドラー呼び出しのマーシャリングを行います。
/// </summary>
/// <typeparam name="TEventHandler">イベントハンドラーの型。</typeparam>
/// <typeparam name="TEventArgs">イベントハンドラーで使用されるイベント引数の型。</typeparam>
/// <param name="synchronizingObject">イベントハンドラーの呼び出しに使用する<see cref="ISynchronizeInvoke"/>。</param>
/// <param name="sender">イベントのソース。</param>
/// <param name="eventHandler">発生させるイベントのイベントハンドラー。</param>
/// <param name="e">発生させるイベントのイベント引数。</param>
// `RaiseEvent` cannot be used to name this method.
public static void Invoke<TEventHandler, TEventArgs>(
ISynchronizeInvoke? synchronizingObject,
object? sender,
TEventHandler? eventHandler,
TEventArgs e
)
where TEventHandler : Delegate
where TEventArgs : EventArgs
{
if (eventHandler is null)
return;

if (synchronizingObject is not null && synchronizingObject.InvokeRequired) {
_ = synchronizingObject.BeginInvoke(
method: eventHandler,
args: [sender, e]
);

return;
}

try {
if (eventHandler is EventHandler<TEventArgs> eventHandlerOfTEventArgs) {
eventHandlerOfTEventArgs.Invoke(sender, e);
}
else {
// in case of XxxEventHandler
eventHandler.DynamicInvoke(sender, e);
#if false
var eventHandlerAction = (Action<object?, TEventArgs>)Delegate.CreateDelegate(
type: typeof(Action<object?, TEventArgs>),
firstArgument: eventHandler.Target,
method: eventHandler.Method,
throwOnBindFailure: true
)!;

eventHandlerAction.Invoke(sender, e);
#endif
}
}
#pragma warning disable CA1031
catch {
// ignore exceptions from event handler
}
#pragma warning restore CA1031
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ SPDX-License-Identifier: MIT

<ItemGroup>
<Compile Include="$(MSBuildThisFileDirectory)..\Common\Shim\System.Linq\EnumerableChunkShim.cs"/>
<Compile Include="$(MSBuildThisFileDirectory)..\Common\Smdn.Net.EchonetLite.ComponentModel\EventInvoker.cs"/>
</ItemGroup>

<Target Name="GenerateReadmeFileContent">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
using System.ComponentModel;
using System.Runtime.CompilerServices;

using Smdn.Net.EchonetLite.ComponentModel;

namespace Smdn.Net.EchonetLite.RouteB.DataAggregation;

/// <summary>
Expand All @@ -25,5 +27,10 @@ private protected SmartMeterDataAggregator GetAggregatorOrThrow()
=> Aggregator ?? throw new InvalidOperationException($"Not associated with the appropriate {nameof(SmartMeterDataAggregator)}.");

protected void OnPropertyChanged([CallerMemberName] string? propertyName = null)
=> GetAggregatorOrThrow().InvokeEvent(this, PropertyChanged, new PropertyChangedEventArgs(propertyName));
=> EventInvoker.Invoke(
GetAggregatorOrThrow().SynchronizingObject,
this,
PropertyChanged,
new PropertyChangedEventArgs(propertyName)
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -173,42 +173,6 @@ protected override void Dispose(bool disposing)
base.Dispose(disposing);
}

internal void InvokeEvent<TEventHandler, TEventArgs>(
object? sender,
TEventHandler? eventHandler,
TEventArgs e
) where TEventHandler : Delegate
{
if (eventHandler is null)
return;

var synchronizingObject = SynchronizingObject;

if (synchronizingObject is null || !synchronizingObject.InvokeRequired) {
var eventHandlerAction = (Action<object?, TEventArgs>)Delegate.CreateDelegate(
type: typeof(Action<object?, TEventArgs>),
firstArgument: eventHandler.Target,
method: eventHandler.Method,
throwOnBindFailure: true
)!;

try {
eventHandlerAction.Invoke(sender, e);
}
#pragma warning disable CA1031
catch {
// ignore exceptions from event handler
}
#pragma warning restore CA1031
}
else {
_ = synchronizingObject.BeginInvoke(
method: eventHandler,
args: [sender, e]
);
}
}

private static readonly TaskFactory DefaultAggregationTaskFactory = new(
cancellationToken: default,
creationOptions: TaskCreationOptions.LongRunning,
Expand Down

This file was deleted.

1 change: 1 addition & 0 deletions src/Smdn.Net.EchonetLite/Smdn.Net.EchonetLite.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ SPDX-License-Identifier: MIT
<ItemGroup>
<Compile Include="$(MSBuildThisFileDirectory)..\Common\Shim\System.Runtime.CompilerServices\IsExternalInit.cs"/>
<Compile Include="$(MSBuildThisFileDirectory)..\Common\Shim\System.Threading.Tasks\TaskCompletionSource.cs"/>
<Compile Include="$(MSBuildThisFileDirectory)..\Common\Smdn.Net.EchonetLite.ComponentModel\EventInvoker.cs"/>
</ItemGroup>

<Target Name="GenerateReadmeFileContent">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,10 +58,10 @@ public ISynchronizeInvoke? SynchronizingObject {
public event EventHandler<EchonetNodeEventArgs>? InstanceListUpdated;

protected virtual void OnInstanceListUpdating(EchonetNodeEventArgs e)
=> RaiseEvent(InstanceListUpdating, e);
=> InvokeEvent(InstanceListUpdating, e);

protected virtual void OnInstanceListUpdated(EchonetNodeEventArgs e)
=> RaiseEvent(InstanceListUpdated, e);
=> InvokeEvent(InstanceListUpdated, e);

/// <summary>
/// プロパティマップの取得を開始するときに発生するイベント。
Expand All @@ -78,48 +78,14 @@ protected virtual void OnInstanceListUpdated(EchonetNodeEventArgs e)
public event EventHandler<EchonetObjectEventArgs>? PropertyMapAcquired;

protected virtual void OnPropertyMapAcquiring(EchonetObjectEventArgs e)
=> RaiseEvent(PropertyMapAcquiring, e);
=> InvokeEvent(PropertyMapAcquiring, e);

protected virtual void OnPropertyMapAcquired(EchonetObjectEventArgs e)
=> RaiseEvent(PropertyMapAcquired, e);

private void RaiseEvent<TEventArgs>(
EventHandler<TEventArgs>? eventHandler,
TEventArgs e
) where TEventArgs : EventArgs
=> InvokeEvent(this, eventHandler, e);

void IEventInvoker.InvokeEvent<TEventArgs>(
object? sender,
EventHandler<TEventArgs>? eventHandler,
TEventArgs e
)
=> InvokeEvent(sender, eventHandler, e);
=> InvokeEvent(PropertyMapAcquired, e);

protected void InvokeEvent<TEventArgs>(
object? sender,
EventHandler<TEventArgs>? eventHandler,
TEventArgs e
)
{
if (eventHandler is null)
return;

if (synchronizingObject is null || !synchronizingObject.InvokeRequired) {
try {
eventHandler(sender, e);
}
#pragma warning disable CA1031
catch {
// ignore exceptions from event handler
}
#pragma warning restore CA1031
}
else {
_ = synchronizingObject.BeginInvoke(
method: eventHandler,
args: [sender, e]
);
}
}
) where TEventArgs : EventArgs
=> EventInvoker.Invoke(synchronizingObject, this, eventHandler, e);
}
8 changes: 4 additions & 4 deletions src/Smdn.Net.EchonetLite/Smdn.Net.EchonetLite/EchonetNode.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Diagnostics.CodeAnalysis;
using System.Net;

Expand Down Expand Up @@ -48,10 +49,9 @@ IEnumerable<EchonetObject> devices
internal IEchonetClientService? Owner { get; private set; }

/// <summary>
/// このインスタンスでイベントを発生させるために使用される<see cref="IEventInvoker"/>を取得します
/// イベントの結果として発行されるイベントハンドラー呼び出しをマーシャリングするために使用する<see cref="ISynchronizeInvoke"/>オブジェクトを取得します
/// </summary>
/// <exception cref="InvalidOperationException"><see cref="IEventInvoker"/>を取得することができません。</exception>
internal IEventInvoker EventInvoker => GetOwnerOrThrow();
internal ISynchronizeInvoke? SynchronizingObject => GetOwnerOrThrow().SynchronizingObject;

/// <summary>
/// このインスタンスを対象とする<see cref="EchonetNodeEventArgs"/>の、作成済みインスタンスを取得します。
Expand Down Expand Up @@ -109,5 +109,5 @@ public bool TryFindDevice(
internal abstract EchonetObject? FindDevice(EOJ eoj);

private protected void OnDevicesChanged(NotifyCollectionChangedEventArgs e)
=> EventInvoker.InvokeEvent(this, DevicesChanged, e);
=> EventInvoker.Invoke(SynchronizingObject, this, DevicesChanged, e);
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
using System.Diagnostics.CodeAnalysis;
using System.Net;

using Smdn.Net.EchonetLite.ComponentModel;

namespace Smdn.Net.EchonetLite;

/// <summary>
Expand Down Expand Up @@ -97,7 +99,7 @@ out EchonetOtherNode addedNode
}

private void OnNodeAdded(EchonetNodeEventArgs e)
=> GetOwnerOrThrow().InvokeEvent(this, NodeAdded, e);
=> EventInvoker.Invoke(GetOwnerOrThrow().SynchronizingObject, this, NodeAdded, e);

internal void SetOwner(IEchonetClientService newOwner)
{
Expand Down
13 changes: 6 additions & 7 deletions src/Smdn.Net.EchonetLite/Smdn.Net.EchonetLite/EchonetObject.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.ComponentModel;

using Smdn.Net.EchonetLite.ComponentModel;
using Smdn.Net.EchonetLite.Protocol;
Expand Down Expand Up @@ -63,11 +64,9 @@ internal EchonetNode? OwnerNode {
#endif

/// <summary>
/// このインスタンスでイベントを発生させるために使用される<see cref="IEventInvoker"/>を取得します
/// イベントの結果として発行されるイベントハンドラー呼び出しをマーシャリングするために使用する<see cref="ISynchronizeInvoke"/>オブジェクトを取得します
/// </summary>
/// <exception cref="InvalidOperationException"><see cref="IEventInvoker"/>を取得することができません。</exception>
protected virtual IEventInvoker EventInvoker
=> OwnerNode?.EventInvoker ?? throw new InvalidOperationException($"{nameof(EventInvoker)} can not be null.");
protected internal virtual ISynchronizeInvoke? SynchronizingObject => Node.SynchronizingObject;

/// <summary>
/// このインスタンスを対象とする<see cref="EchonetObjectEventArgs"/>の、作成済みインスタンスを取得します。
Expand Down Expand Up @@ -139,10 +138,10 @@ internal abstract void ApplyPropertyMap(
);

private protected void OnPropertiesChanged(NotifyCollectionChangedEventArgs e)
=> EventInvoker.InvokeEvent(this, PropertiesChanged, e);
=> EventInvoker.Invoke(SynchronizingObject, this, PropertiesChanged, e);

protected internal void OnPropertyValueUpdated(EchonetPropertyValueUpdatedEventArgs e)
=> EventInvoker.InvokeEvent(this, PropertyValueUpdated, e);
=> EventInvoker.Invoke(SynchronizingObject, this, PropertyValueUpdated, e);

internal void RaisePropertyValueUpdated(
EchonetProperty property,
Expand All @@ -164,7 +163,7 @@ DateTime previousUpdatedTime
updatedTime: property.LastUpdatedTime
);

EventInvoker.InvokeEvent(property, valueUpdatedEventHandler, e);
EventInvoker.Invoke(SynchronizingObject, property, valueUpdatedEventHandler, e);

OnPropertyValueUpdated(e);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using System;
#endif
using System.Collections.Generic;
using System.ComponentModel;
using System.Net;
using System.Threading;
using System.Threading.Tasks;
Expand All @@ -12,7 +13,6 @@

using Polly;

using Smdn.Net.EchonetLite.ComponentModel;
using Smdn.Net.EchonetLite.Protocol;

namespace Smdn.Net.EchonetLite;
Expand All @@ -21,7 +21,12 @@ namespace Smdn.Net.EchonetLite;
/// ECHONET Lite 通信ミドルウェアを実装する<see cref="EchonetClient"/>クラスと、ECHONET ノードを実装する<see cref="EchonetNode"/>および
/// ECHONET オブジェクトを実装する<see cref="EchonetObject"/>との間で協調動作するための機能へのインターフェイスを提供します。
/// </summary>
internal interface IEchonetClientService : IEventInvoker {
internal interface IEchonetClientService {
/// <summary>
/// イベントの結果として発行されるイベントハンドラー呼び出しをマーシャリングするために使用する<see cref="ISynchronizeInvoke"/>オブジェクトを取得または設定します。
/// </summary>
ISynchronizeInvoke? SynchronizingObject { get; set; }

#if SYSTEM_TIMEPROVIDER
/// <summary>
/// <see cref="EchonetProperty.LastUpdatedTime"/>に設定する時刻の取得元となる<see cref="TimeProvider"/>を取得します。
Expand Down
Loading

0 comments on commit c296d61

Please sign in to comment.