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:identifier metadata;
  • you remap an enclosing module using the java:package metadata, 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:

Java
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:identifier metadata; 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:

MATLAB
communicator = Ice.Communicator(args, SliceLoader = Ice.ClassSliceLoader(?Compact, ?CompactExt));

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:

C++
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:

C#
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:

Java
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:

TypeScript
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:

MATLAB
classdef NodeLoader < Ice.SliceLoader
methods
function r = newInstance(~, typeId)
if strcmp(typeId, '::Demo::Node')
r = MyNode();
else
r = [];
end
end
end
end

You install it with the SliceLoader argument of the Ice.Communicator constructor:

MATLAB
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:

Python
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:

Ruby
class NodeLoader
def newInstance(typeId)
typeId == "::Demo::Node" ? MyNode.new : nil
end
end
initData = Ice::InitializationData.new
initData.sliceLoader = NodeLoader.new
Ice.initialize(initData) do |communicator|
...
end

Ice 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:

Swift
final class NodeLoader: SliceLoader {
func newInstance(_ typeId: String) -> AnyObject? {
typeId == "::Demo::Node" ? MyNode() : nil
}
}
let communicator = try Ice.initialize(Ice.InitializationData(sliceLoader: NodeLoader()))