Skip to content

Commit

Permalink
Merge pull request #26 from cwollenhaupt/master
Browse files Browse the repository at this point in the history
Subscribe only to implemented events
  • Loading branch information
RickStrahl authored Dec 6, 2024
2 parents f9ba11c + 109a68a commit b155769
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 17 deletions.
17 changes: 8 additions & 9 deletions Distribution/wwDotnetBridge.PRG
Original file line number Diff line number Diff line change
Expand Up @@ -252,7 +252,7 @@ ENDFUNC
*** Function: Unloads the CLR and AppDomain
*** Assume: Don't call this unless you want to explicity force
*** the AppDomain to be unloaded and a new one to be spun
*** up. Generally a single domain shoudl be sufficient.
*** up. Generally a single domain should be sufficient.
*** Pass:
*** Return:
************************************************************************
Expand Down Expand Up @@ -473,8 +473,7 @@ DO CASE
ENDCASE

IF loBridge.Error
this.cErrorMsg = loBridge.ErrorMessage
this.lError = .T.
this.SetError(loBridge.ErrorMessage)
ENDIF

RETURN loResult
Expand Down Expand Up @@ -526,8 +525,7 @@ ENDCASE
loResult = loBridge.InvokeMethod_ParameterArray(loObject, lcMethod, loArray)

IF loBridge.Error
this.cErrorMsg = loBridge.ErrorMessage
this.lError = .T.
this.SetError(loBridge.ErrorMessage)
ENDIF

RETURN loResult
Expand Down Expand Up @@ -789,8 +787,7 @@ DO CASE
ENDCASE

IF loBridge.Error
this.cErrorMsg = loBridge.ErrorMessage
this.lError = .T.
this.SetError(loBridge.ErrorMessage)
ENDIF

RETURN loResult
Expand Down Expand Up @@ -1818,7 +1815,9 @@ FUNCTION Setup(loBridge, loSource, loHandler, lcPrefix)
this.oBridge = loBridge
this.oHandler = loHandler
this.oPrefix = lcPrefix
this.oSubscriber = loBridge.CreateInstance("Westwind.WebConnection.EventSubscriber", loSource)
Private handler
handler = m.loHandler
this.oSubscriber = loBridge.CreateInstance("Westwind.WebConnection.EventSubscriber", loSource, m.lcPrefix, _Vfp)
this.HandleNextEvent()
ENDFUNC

Expand Down Expand Up @@ -2017,7 +2016,7 @@ ENDFUNC
*** Function: Unloads the CLR and AppDomain
*** Assume: Don't call this unless you want to explicity force
*** the AppDomain to be unloaded and a new one to be spun
*** up. Generally a single domain shoudl be sufficient.
*** up. Generally a single domain should be sufficient.
*** Pass:
*** Return:
************************************************************************
Expand Down
31 changes: 24 additions & 7 deletions DotnetBridge/Utilities/EventSubscriber.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,18 +16,24 @@ namespace Westwind.WebConnection
public sealed class EventSubscriber : IDisposable
{
private readonly object _source;
private readonly List<Delegate> _eventHandlers = new List<Delegate>();
private readonly List<DelegateInfo> _eventHandlers = new List<DelegateInfo>();
private readonly ConcurrentQueue<RaisedEvent> _raisedEvents = new ConcurrentQueue<RaisedEvent>();
private TaskCompletionSource<RaisedEvent> _completion = new TaskCompletionSource<RaisedEvent>();

public EventSubscriber(object source)
public EventSubscriber(object source, String prefix = "", dynamic vfp = null)
{
// Indicates that initially the client is not waiting.
_completion.SetResult(null);

// For each event, adds a handler that calls QueueInteropEvent.
_source = source;
foreach (var ev in source.GetType().GetEvents()) {
foreach (var ev in source.GetType().GetEvents())
{
// handler is a PRIVATE variable defined in EventSubscription.Setup().
Boolean hasMethod = vfp?.Eval($"PEMSTATUS(m.handler, '{prefix}{ev.Name}', 5)") ?? true;
if (!hasMethod)
continue;

var eventParams = ev.EventHandlerType.GetMethod("Invoke").GetParameters().Select(p => Expression.Parameter(p.ParameterType)).ToArray();
var eventHandlerLambda = Expression.Lambda(ev.EventHandlerType,
Expression.Call(
Expand All @@ -38,15 +44,26 @@ public EventSubscriber(object source)
eventParams);
var eventHandler = eventHandlerLambda.Compile();
ev.AddEventHandler(source, eventHandler);
_eventHandlers.Add(eventHandler);
_eventHandlers.Add(new DelegateInfo(eventHandler, ev));
}
}

class DelegateInfo
{
public DelegateInfo(Delegate handler, EventInfo eventInfo)
{
Delegate = handler;
EventInfo = eventInfo;
}

public Delegate Delegate { get; }
public EventInfo EventInfo { get; }
}

public void Dispose()
{
var events = _source.GetType().GetEvents();
for (int e = 0; e < events.Length; ++e)
events[e].RemoveEventHandler(_source, _eventHandlers[e]);
foreach (var item in _eventHandlers)
item.EventInfo.RemoveEventHandler(_source, item.Delegate);
_completion.TrySetCanceled();
}

Expand Down
2 changes: 1 addition & 1 deletion DotnetBridge/wwDotNetBridge.cs
Original file line number Diff line number Diff line change
Expand Up @@ -279,7 +279,7 @@ protected internal object CreateInstance_Internal(string TypeName, params object

if (type == null)
{
SetError("Type not loaded. Please load call LoadAssembly first.");
SetError("Type not loaded. Please call LoadAssembly first.");
return null;
}

Expand Down

0 comments on commit b155769

Please sign in to comment.