C
C#2y ago
xonery

❔ Generics

Hi, I commented the code to explain my issue
public async Task DispatchAsync(IEventContext context)
{
var @event = _dictionary.Resolve<IEvent<TAggregateIdentifier>, TAggregateIdentifier>(context.Identifier, context.Payload);

// 1. So far
// @event.GetType() -> MyEvent

await _domain.HandleDomainAsync(@event);
}

public async Task HandleDomainAsync<TEvent>(TEvent @event) where TEvent : IEvent<TAggregateIdentifier>
{
// 2. So far
// typeof(TEvent) -> IEvent<TAggregateIdentifier>
// @event.GetType() -> MyEvent

// 3. I have to use MakeGenericType to retrieve a list of IDomainEventHandler<TAggregateRoot, TAggregateIdentifier, MyEvent>
// as i cannot use TEvent directly.

var type = typeof(IDomainEventHandler<,,>).MakeGenericType(typeof(TAggregateRoot), typeof(TAggregateIdentifier),
@event.GetType());

var service = _services.GetService(type);

// 4. As GetService returned an object, I have to cast to IDomainEventHandler<TAggregateRoot, TAggregateIdentifier, TEvent>
// so i can call service.HandleAsync(@event)

// 5. This doesn't work tho, as typeof(TEvent) -> IEvent<TAggregateIdentifier>, witch makes sence
if(service is IDomainEventHandler<TAggregateRoot, TAggregateIdentifier, TEvent> handler)
await handler.HandleAsync(@event);

// Question: I there any way I can make it working without using reflection to invoke HandleAsync ?
//
}
public async Task DispatchAsync(IEventContext context)
{
var @event = _dictionary.Resolve<IEvent<TAggregateIdentifier>, TAggregateIdentifier>(context.Identifier, context.Payload);

// 1. So far
// @event.GetType() -> MyEvent

await _domain.HandleDomainAsync(@event);
}

public async Task HandleDomainAsync<TEvent>(TEvent @event) where TEvent : IEvent<TAggregateIdentifier>
{
// 2. So far
// typeof(TEvent) -> IEvent<TAggregateIdentifier>
// @event.GetType() -> MyEvent

// 3. I have to use MakeGenericType to retrieve a list of IDomainEventHandler<TAggregateRoot, TAggregateIdentifier, MyEvent>
// as i cannot use TEvent directly.

var type = typeof(IDomainEventHandler<,,>).MakeGenericType(typeof(TAggregateRoot), typeof(TAggregateIdentifier),
@event.GetType());

var service = _services.GetService(type);

// 4. As GetService returned an object, I have to cast to IDomainEventHandler<TAggregateRoot, TAggregateIdentifier, TEvent>
// so i can call service.HandleAsync(@event)

// 5. This doesn't work tho, as typeof(TEvent) -> IEvent<TAggregateIdentifier>, witch makes sence
if(service is IDomainEventHandler<TAggregateRoot, TAggregateIdentifier, TEvent> handler)
await handler.HandleAsync(@event);

// Question: I there any way I can make it working without using reflection to invoke HandleAsync ?
//
}
4 Replies
phaseshift
phaseshift2y ago
// as i cannot use TEvent directly.
why? Regardless, it seems you want to be calling a generic method from a non-generic base class. There is a pattern that can do this for you with a bit of casting.
interface IBase
{
void foo(object o);
}

abstract class Base<T> : IBase
{
void foo(T t) {...};

void food(object o) => foo((T)o);
}
interface IBase
{
void foo(object o);
}

abstract class Base<T> : IBase
{
void foo(T t) {...};

void food(object o) => foo((T)o);
}
It's a bit ugly, but it lets you pass IBase around and call foo with a T as long as you know its right
xonery
xonery2y ago
Thanks for taking the time to read my post
// So far, I cannot use TEvent for the cast as
IDomainEventHandler<TAggregateRoot, TAggregateIdentifier, TEvent>
// Is resolved as
IDomainEventHandler<MyAggregateRoot, MyAggregateIdentifier, IEvent<MyAggregateIdentifier>>
// And not
IDomainEventHandler<MyAggregateRoot, MyAggregateIdentifier, MyEvent>
// As I expected it to be, so the cast fails
// So far, I cannot use TEvent for the cast as
IDomainEventHandler<TAggregateRoot, TAggregateIdentifier, TEvent>
// Is resolved as
IDomainEventHandler<MyAggregateRoot, MyAggregateIdentifier, IEvent<MyAggregateIdentifier>>
// And not
IDomainEventHandler<MyAggregateRoot, MyAggregateIdentifier, MyEvent>
// As I expected it to be, so the cast fails
The pattern you showed works as expected but yea looks kinda ugly as i will need a Base class to wrap the casting... I would LOVE TEvent to be Resolved as MyEvent and not IEvent<MyAggregateIdentity>
if(service is IEventHandler handler)
await handler.HandleAsync(@event);
if(service is IEventHandler handler)
await handler.HandleAsync(@event);
phaseshift
phaseshift2y ago
Yup. or switch to cpp and wait for 'deducing this' 😅
Accord
Accord2y ago
Was this issue resolved? If so, run /close - otherwise I will mark this as stale and this post will be archived until there is new activity.