Skip to content

Usage.Custom Services

JuDelCo edited this page Jun 1, 2021 · 9 revisions

Namespaces: Ju.Services & Ju.Services.Extensions


Services are a great way to have a piece of code with state anywhere avaliable.

If you don't need state, you may consider using extension methods instead (functional programming).

It's not recommended for handling references or manipulating GameObjects in a Unity scene, use MonoBehaviours for that.

IService

Services must implement the IService interface. This interface has no methods or properties, so you're free to design your service as you want.

public class MyCustomService : IService
{
	public void MyPublicMethod()
	{
		// Do something
	}
}

But there are two special interfaces (that implement IService as well) that can be used for special requirements:

IServiceLoad

void Load();

The IServiceLoad interface provides one method that will be called when the service is created (when will depend of how it was registered, you can learn more about the Service Container here).

public class MyCustomService : IServiceLoad
{
	private IMyOtherCustomService otherService;

	public void Load()
	{
		// Initialize your service.

		// Get and cache other service references (after initialization).
		otherService = Core.Get<IMyOtherCustomService>();
	}

	public void MyPublicMethod()
	{
		// Do something (you can use the cached 'otherService' reference)
	}
}

Just make sure that the service is fully initialized before getting other service references. That will prevent circular dependencies (if any) related problems.

IServiceUnload

void Unload();

The IServiceUnload interface implements one method that will be called on Service Container dispose (when closing the application) or when the service gets unloaded manually.

public class MyCustomService : IServiceUnload
{
	public void Unload()
	{
		// Dispose all resources here.
	}

	public void MyPublicMethod()
	{
		// Do something
	}
}

IService Extensions

These extensions can be used inside of a custom service that implements the IService interface.

You only need to add using Ju.Services.Extensions; and you're ready.

void EventSubscribe<T>(Action<T> action, int priority = 0);
void EventSubscribe<T>(Action action, int priority = 0);
void EventSubscribe<T>(Action<T> action, Func<T, bool> filter, int priority = 0);
void EventSubscribe<T>(Action action, Func<T, bool> filter, int priority = 0);
void EventSubscribe<T>(byte channel, Action<T> action, int priority = 0);
void EventSubscribe<T>(byte channel, Action action, int priority = 0);
void EventSubscribe<T>(byte channel, Action<T> action, Func<T, bool> filter, int priority = 0);
void EventSubscribe<T>(byte channel, Action action, Func<T, bool> filter, int priority = 0);

Coroutine CoroutineStart(IEnumerator routine);

IPromise WaitUntil(Func<bool> condition);
IPromise WaitWhile(Func<bool> condition);
IPromise WaitForSeconds<T>(float seconds) where T : ITimeDeltaEvent;
IPromise WaitForSeconds(float seconds);
IPromise WaitForTicks<T>(int ticks) where T : ITimeEvent;
IPromise WaitForNextUpdate();
IPromise WaitForNextFixedUpdate();

IClock NewClock<T>() where T : ITimeDeltaEvent;
IClock NewClock<T>(float elapsedSeconds) where T : ITimeDeltaEvent;
ITimer NewTimer<T>(float seconds, Action onCompleted) where T : ITimeDeltaEvent;
IFrameTimer NewFrameTimer<T>(int frames, Action onCompleted) where T : ITimeEvent;

void NodeSubscribe(JNode node, Action<JNode, JNodeEvent> action);
void NodeSubscribe(JNode node, JNodeEvent eventFilter, Action<JNode> action);
void NodeSubscribe<T>(JNode node, JNodeEvent eventFilter, Action<T> action) where T : JNode;
void NodeSubscribe(JNode node, Action action);
void NodeSubscribe(JNode node, JNodeEvent eventFilter, Action action);
void DataSubscribe<T>(JData<T> node, Action<JData<T>> action);
Action<T> DataBind<T>(JData<T> node, Action<JData<T>> action);
Action<TRemote> DataBind<T, TRemote>(JData<T> node, Action<JData<T>> action, Func<TRemote, T> converter);

Full example

// Simple minimal service example
public class MySimpleCustomService : IService
{
	public void MySimplePublicMethod()
	{
		// Do something
	}
}

// Interface for the full custom service example
public interface IMyCustomService
{
	void MyPublicMethod();
}

// Custom service that implements all three interfaces
public class MyCustomService : IMyCustomService, IServiceLoad, IServiceUnload
{
	private IMyOtherCustomService otherService;

	public void Load()
	{
		// Initialize your service.

		// Get and cache other service references (after initialization).
		otherService = Core.Get<IMyOtherCustomService>();

		// Subscribe Events
		this.EventSubscribe<CustomEvent>(MyEventCallback);
	}

	public void Unload()
	{
		// Dispose resources here.
	}

	public void MyPublicMethod()
	{
		// Do something
	}
}

Don't forget to register your services first so you can use them later (See Getting Started to read more about this step)

// Register the services (see Getting Started) ...
ServiceContainer.RegisterService<MySimpleCustomService, MySimpleCustomService>();
ServiceContainer.RegisterService<IMyCustomService, MyCustomService>();


// ... then, later in your code:
var simpleService = ServiceContainer.Get<MySimpleCustomService>();
var complexService = ServiceContainer.Get<IMyCustomService>();

simpleService.MySimplePublicMethod();
complexService.MyPublicMethod();

Remember to add using Ju.Services.Extensions; at the top of your file if you want to use the extension methods.

Clone this wiki locally