C
C#2y ago
Kiel

Using a derived type in Action

I'm deriving from an abstract class whose constructor accepts an object of type Action<LocalMessageBase>. LocalMessageBase is an abstract class, of which there are a few derived classes, of which one is LocalInteractionMessageResponse. Is there a way to use this derived type for the action instead of the base type, either directly within the action, or via some other casting magic? This is what I tried to no avail:
public class MyView : ViewBase
{
public MyView(Action<LocalInteractionMessageResponse> messageTemplate)
: base(messageTemplate)
{ }
}
public class MyView : ViewBase
{
public MyView(Action<LocalInteractionMessageResponse> messageTemplate)
: base(messageTemplate)
{ }
}
though casting messageTemplate to Action<LocalMessageBase> doesn't cause any warning/hint lints in VS or via R#?
3 Replies
Kouhai
Kouhai2y ago
You can cast Action<LocalInteractionMessageResponse>to Action<LocalMessageBase> at runtime it'll throw InvalidCastException You can however do something like this
abstract class BaseAction<T> where T : LocalMessageBase
{
public BaseAction(Action<T> action) { }
}

class LocalInteractionMessageResponseAction : BaseAction<LocalInteractionMessageResponse>
{
public LocalInteractionMessageResponseAction(Action<LocalInteractionMessageResponse> action) : base(action) { }
}

class LocalInteractionMessageResponse : LocalMessageBase
{
}
abstract class LocalMessageBase
{
}
abstract class BaseAction<T> where T : LocalMessageBase
{
public BaseAction(Action<T> action) { }
}

class LocalInteractionMessageResponseAction : BaseAction<LocalInteractionMessageResponse>
{
public LocalInteractionMessageResponseAction(Action<LocalInteractionMessageResponse> action) : base(action) { }
}

class LocalInteractionMessageResponse : LocalMessageBase
{
}
abstract class LocalMessageBase
{
}
Kiel
Kiel2y ago
how would this solution apply to my example exactly? if it removes any additional confusion, this ViewBase class I am deriving is third-party and I can't modify it, as well as any of the LocalMessageBase + derived classes
Kouhai
Kouhai2y ago
If you can't modify them, I'd do
class MyView : ViewBase
{
public MyView(Action<LocalInteractionMessageResponse> action) : base((m) => action(m as LocalInteractionMessageResponse))
{

}
}
class MyView : ViewBase
{
public MyView(Action<LocalInteractionMessageResponse> action) : base((m) => action(m as LocalInteractionMessageResponse))
{

}
}
Or if I'm going to be deriving from ViewBase a lot, I'd just do
static class Extensions
{
public static Action<LocalMessageBase> AsBase<T>(this Action<T> action) where T : LocalMessageBase
{
return (m) => action(m as T);
}
}

class MyView : ViewBase
{
public MyView(Action<LocalInteractionMessageResponse> action) : base(action.AsBase())
{

}
}
static class Extensions
{
public static Action<LocalMessageBase> AsBase<T>(this Action<T> action) where T : LocalMessageBase
{
return (m) => action(m as T);
}
}

class MyView : ViewBase
{
public MyView(Action<LocalInteractionMessageResponse> action) : base(action.AsBase())
{

}
}
@Kiel