I am working on an ASP.NET Core MVC web app.
I have a domain object method which calls a method of a 3rd party library. If something is wrong with the execution of the method, a callback function will be called.
My purpose is to pass the result of the callback function to a service which passes variables to the controller and view. I implemented it with 2 approaches.
Approach 1: temporarily store the result in a member variable of custom event handler
Approach 2: temporarily store the result in .NET Core HttpContext.Items.
Both worked but the app became super slow with Approach 2; HttpContext seems to be overkill for this.
Did I misuse HttpContext in approach 2?
Approach 1 looks like Javascript styled event handlers which have public member variables. So far I didn't see any performance issue with it. Any cons you see in approach 1?
Any suggestion of other approach?
This is roughly how I did it.
Approach 1
Class ServiceA:
private IEventBus _eventBus;
private MyEventHandler _eventHandler;
public ServiceA(IEventBus eventBus, MyEventHandler eventHandler)
{
_eventBus = eventBus;
_eventHandler = eventHandler;
}
public MyDTO DoSthA(string arg)
{
DomainA domainObj = new DomainA(_eventBus);
domainObj.doSth(arg);
MyDTO ret = new MyDTO();
ret.EventResult = _eventHandler.Result;
return ret;
}
Class DomainA
private readonly IEventBus _eventBus;
private readonly Some3rdPartyStuff _some3rdPartyStuff;
public DomainA(IEventBus eventBus)
{
_eventBus = eventBus;
_some3rdPartyStuff = new Some3rdPartyStuff();
// configuration of the 3rd party library object
_some3rdPartyStuff.OnSomeEvent(
var event = new MyEvent();
// setting event member variables
_eventBus.Dispatch(event);
)
}
public void DoSth(string arg)
{
_some3rdPartyStuff.doSth(arg);
}
Event Bus (singleton scoped)
public interface IEventBus
{
void Dispatch<TEvent>(TEvent @event) where TEvent : IEvent;
}
public class MyEventBus : IEventBus
{
public void Dispatch<TEvent>(TEvent @event) where TEvent : IEvent
{
if (@event == null)
throw new ArgumentNullException("event");
var handlerType = typeof(IEventHandler<>).MakeGenericType(@event.GetType());
dynamic handlers = DIContainer.INSTANCE.GetAllInstances<IEventHandler<TEvent>>();
foreach (var handler in handlers)
{
handler.Handle(@event);
}
}
Ref: Implementing Domain Event Handler pattern in C# with Simple Injector
Event Handler (Request scoped)
public interface IEventHandler<TEvent>
{
void Handle(TEvent @event);
}
public class MyEventHandler : IEventHandler<MyEvent>
{
public EventResult Result { get; private set; }
public void Handle(MyEvent @event) {
var result = new EventResult();
// setting variables of EventResult
Result = result;
}
}
Approach 2
Class ServiceA
private IEventBus _eventBus;
private IHttpContextAccessor _httpContextAccessor;
public ServiceA(IEventBus eventBus, IHttpContextAccessor httpContextAccessor){
_eventBus = eventBus;
_httpContextAccessor = httpContextAccessor;
}
public MyDTO DoSthA(string arg){
DomainA domainObj = new DomainA(_eventBus);
domainObj.doSth(arg);
bool eventHandled = _httpContextAccessor.HttpContext.Items.Contins("key");
MyDTO ret = new MyDTO();
ret.EventResult = eventHandled ? _httpContextAccessor.HttpContext.Items[”key”] : new MyEventResult(); // default result value
return ret;
}
Event Handler (Request scoped)
public interface IEventHandler<TEvent>
{
void Handle(TEvent @event);
}
public class MyEventHandler : IEventHandler<MyEvent>
{
public MyEventHandler(IHttpContextAccessor httpContextAccessor){
_httpContextAccessor = httpContextAccessor;
}
public void Handle(MyEvent @event) {
var result = new EventResult();
// setting variables of EventResult
_httpContextAccessor.HttpContext.Items["key"]= result;
}
}