Slice Loaders
2 min read
2 min read
3 min read
2 min read
3 min read
2 min read
2 min read
2 min read
When Ice unmarshals a Slice-defined class or exception, it starts by locating the mapped class and creating an instance of this class.
The abstraction that drives this locate and create process is called the Slice loader. Each communicator has a default Slice loader, implemented by Ice, that locates the generated class for a Slice type ID.
The default Slice loader of Ice for Java converts the Slice type ID into a Java class name: for the type ID ::Demo::Node, it loads the class Demo.Node. It cannot locate the class for a Slice class or exception when:
- you remap either the class name or an enclosing module using the
java:identifiermetadata; - you remap an enclosing module using the
java:packagemetadata, and set neither the matching Ice.Package.module property nor Ice.Default.Package; or - you assign a compact ID to the class.
For these classes, install a ClassSliceLoader created from the generated classes as your custom Slice loader (see below); the communicator keeps using its default Slice loader for all other classes:
var initData = new InitializationData();initData.sliceLoader = new ClassSliceLoader(Compact.class, CompactExt.class);The default Slice loader of Ice for MATLAB converts the Slice type ID into a MATLAB class name, for example ::M::Node into M.Node. It cannot locate the class for a Slice class or exception when:
- you remap either the class name or an enclosing module using the
matlab:identifiermetadata; or - you assign a compact ID to the class.
For these classes, create an Ice.ClassSliceLoader from the meta classes of the generated classes and install it as your custom Slice loader (see below); the communicator keeps using its default Slice loader for all other classes:
communicator = Ice.Communicator(args, SliceLoader = Ice.ClassSliceLoader(?Compact, ?CompactExt));Custom Slice Loaders
You can install your own custom Slice loader on a communicator to create instances of your own classes, typically classes derived from the generated classes, during unmarshaling. The communicator calls your Slice loader first, and falls back on its default Slice loader when your Slice loader doesn't create an instance.
The communicator calls your Slice loader for both Slice classes and Slice exceptions.
A custom Slice loader derives from Ice::SliceLoader and overrides newClassInstance, newExceptionInstance, or both. You install it by setting the sliceLoader field of InitializationData:
class NodeLoader final : public Ice::SliceLoader{public: [[nodiscard]] Ice::ValuePtr newClassInstance(std::string_view typeId) const final { return typeId == "::Demo::Node" ? std::make_shared<MyNode>() : nullptr; }};
Ice::InitializationData initData;initData.sliceLoader = std::make_shared<NodeLoader>();Ice::CommunicatorPtr communicator = Ice::initialize(initData);Ice::CommunicatorHolder communicatorHolder{communicator};A custom Slice loader implements the Ice.SliceLoader interface. You install it by setting the sliceLoader property of InitializationData:
class NodeLoader : Ice.SliceLoader{ public object? newInstance(string typeId) => typeId == "::Demo::Node" ? new MyNode() : null;}
await using var communicator = new Ice.Communicator(new Ice.InitializationData { sliceLoader = new NodeLoader() });A custom Slice loader implements the SliceLoader functional interface. You install it by setting the sliceLoader field of InitializationData:
var initData = new InitializationData();initData.sliceLoader = typeId -> "::Demo::Node".equals(typeId) ? new MyNode() : null;try (var communicator = new Communicator(initData)) { ...}A custom Slice loader is an object with a newInstance method. You install it by setting the sliceLoader property of InitializationData:
const initData = new Ice.InitializationData();initData.sliceLoader = { newInstance: (typeId: string) => (typeId === "::Demo::Node" ? new MyNode() : null),};await using communicator = new Ice.Communicator(initData);A custom Slice loader derives from Ice.SliceLoader and implements its newInstance method, which takes a type ID and returns a new instance:
classdef NodeLoader < Ice.SliceLoader methods function r = newInstance(~, typeId) if strcmp(typeId, '::Demo::Node') r = MyNode(); else r = []; end end endendYou install it with the SliceLoader argument of the Ice.Communicator constructor:
communicator = Ice.Communicator(args, SliceLoader = NodeLoader());Ice for PHP does not let you install a custom Slice loader: when it unmarshals a Slice class or exception, it always creates an instance of the class generated by slice2php.
A custom Slice loader is a callable that takes a type ID and returns a new instance. You install it by setting the sliceLoader field of InitializationData:
def node_loader(typeId: str) -> Ice.Value | None: return MyNode() if typeId == "::Demo::Node" else None
initData = Ice.InitializationData(sliceLoader=node_loader)with Ice.Communicator(initData=initData) as communicator: ...Ice for Python calls your Slice loader only for Slice classes: for a Slice exception, it always creates an instance of the class generated by slice2py.
A custom Slice loader is an object with a newInstance method that takes a type ID and returns a new instance. You install it by setting the sliceLoader attribute of InitializationData:
class NodeLoader def newInstance(typeId) typeId == "::Demo::Node" ? MyNode.new : nil endend
initData = Ice::InitializationData.newinitData.sliceLoader = NodeLoader.newIce.initialize(initData) do |communicator| ...endIce for Ruby calls your Slice loader only for Slice classes: for a Slice exception, it always creates an instance of the class generated by slice2rb.
A custom Slice loader conforms to the SliceLoader protocol. You install it by setting the sliceLoader property of InitializationData:
final class NodeLoader: SliceLoader { func newInstance(_ typeId: String) -> AnyObject? { typeId == "::Demo::Node" ? MyNode() : nil }}
let communicator = try Ice.initialize(Ice.InitializationData(sliceLoader: NodeLoader()))