How to downcast if the derived object type is not known

I have a sequence that generates various types of transactions - say txn_a, txn_b, and txn_c - all derived from the base class txn_base. The derived transactions are sent to different components (sequence to driver, driver to predictor) using the base class handle. In the received component (eg predictor) how do I figure out the derived transaction type so that I downcast the base transaction to its actual derived type? In the past, I add txn_type property that would get set in the extended class. But is there a way achieve same thing using get_type or get_object_type UVM built in functions? If so, can someone provide example? I am not familiar with how these functions work.
Thanks!

In order to do this, you have to know what possible extended types are available.

You can try using a dynamic $cast successfully on each type until you get a success. Or you can use a case statement.

get_object_type() is a virtual method that returns a singleton to the proxy object representing the derived object’s type. get_type() is a static method that that also returns the singleton that can be compared to what get_object_type returns.

import uvm_pkg::*;
`include "uvm_macros.svh"

class txn_base extends uvm_sequence_item;
  `uvm_object_utils(txn_base)
  function new(string name="base");
    super.new(name);
  endfunction
endclass
class txn_a extends txn_base;
  `uvm_object_utils(txn_a)
  function new(string name="a");
    super.new(name);
  endfunction
endclass
class txn_b extends txn_base;
  `uvm_object_utils(txn_b)
  function new(string name="b");
    super.new(name);
  endfunction
endclass
class txn_c extends txn_base;
  `uvm_object_utils(txn_c)
  function new(string name="c");
    super.new(name);
  endfunction
endclass
module top;
  
  txn_base base_h;
  txn_a a_h;
  txn_b b_h;
  txn_c c_h;
  
  initial begin
    b_h = new;
    base_h = b_h;
    //method 1
    if ($cast(a_h,base_h))
      $display("have a txn_a");
    else if ($cast(b_h,base_h))
      $display("have a txn_b");
    else if ($cast(c_h,base_h))
      $display("have a txn_c");
 
    // method 2
   case(base_h.get_object_type())
      txn_a::get_type(): $display("have a txn_a");
      txn_b::get_type(): $display("have a txn_b");
      txn_c::get_type(): $display("have a txn_c");
    endcase
  end
endmodule