#Call method with a generic type

1 messages · Page 1 of 1 (latest)

grave ice
#

I am using a method with a generic type T and need to call this method. The trick is that it can be of any child class from one class, so I would need the method call to be generic too. Is there a way to do that? Here's what I tried, by getting the type I needed, but it doesn't work since it's a variable:

private void InitializeEffects(PlainEffect[] _effects)
{
    foreach (PlainEffect _effect in _effects)
    {
        Type _type = ConditionController.GetTypeByEnum(_effect.effectTrigger);
        _effect.SubscribeEffect<_type>();
    }
}
#

And the method I'm calling:

public override void SubscribeEffect<T>()
{
    ActionSystem.SubscribeReaction<T>(DrawCard, reactionTiming);
}
jovial oasis
#

Someone else will have to tap in with help adjusting to a different solution but short answer here is no, there’s no intended way to do what you want here

#

Using generic stuff needs you to be explicit in typing at at least 1 point in whatever code is involved

grave ice
#

Aw too bad, thanks
I was kinda expecting it, but it would have saved me so much time

fiery warren
#

Maybe pass in the effect effectTrigger instead of trying to pass in its type with generics?

#
_effect.SubscribeEffect(_effect.effectTrigger);
...
ActionSystem.SubscribeReaction(effectTrigger, DrawCard, reactionTiminig);```
Wouldn't the effect instance have everything you need? What happens in SubscribeReaction (and onwards)?
jovial oasis
#

I can’t pinpoint the issue specifically here but your line of thinking using generics like this and Type references in general is a pretty common misunderstanding of how to solve these kinds of problems afaik. Usually the solution involves heavier usage of inheritance to handle certain type assumptions and per type work.

#

Just saying as a general vibe check

grave ice
#

I'd like to but I really need to pass <T> to call the subscribe reaction method, because it's a system using dictionaries with the type as key

fiery warren
#

You could just pass it in and then call .GetType() on the instance and use that as the key

#

So if your SubscribeEffect<T>(...) does currently something like dictionary.Add(typeof(T), ...

#

You could just pass the instance and do dictionary.Add(thing.GetType(), ...

#

What kind of type is effectTrigger?

grave ice
#

This is what SubscribeReaction looks like :

public static void SubscribeReaction<T>(Action<T> _reaction, E_ReactionTiming _timing) where T : GameAction
{
    Dictionary<Type, List<Action<GameAction>>> _subs = _timing == E_ReactionTiming.PRE ? preSubs : postSubs;

    if (wrappedDelegates.ContainsKey(_reaction)) return;

    Action<GameAction> _wrappedReaction = action => _reaction((T)action);
    wrappedDelegates[_reaction] = _wrappedReaction;

    if (!_subs.TryGetValue(typeof(T), out var _list))
    {
        _list = new List<Action<GameAction>>();
        _subs[typeof(T)] = _list;
    }

    _list.Add(_wrappedReaction);
}
fiery warren
#

You can use generics here too, if I understand your system correctly
E: Ok I misunderstood, don't let me confuse further lol

grave ice
#

I'm trying to find a way to rework Subscribe Reaction, but I'm afraid it would affect too much other scripts
Maybe I should just change how I call the method

#

The dirty way would be to hardcode the calls with a switch

#

Dirty but might work

fiery warren
#

Sometimes hardcoded enum switches are better than going to generics hell and overengineering

golden pewter
#

Interfaces usually help bridge the ambiguity if you don't want explicit typings at times

#

then afterwards you can always type check it if needed

grave ice
golden pewter
#

Usually if I do use generics outside of some wrapper class I'd always have some constraints

#

which then halfway through I think to myself that I should have just done some type checking and removed most of the hassle

grave ice
#

mm I see

#

I think I'll go for the hardcode option, it looks easy to implement and does not affect in any way other stuff

#

Thanks everyone!

crude wing
#

I suppose you can't just accept Action<GameAction>, because Action<SpecificGameAction> is not a compatible type

grave ice
#

Yeah there would be a limitation with the gameactions I can pass in