vovgou / loxodon-framework

An MVVM & Databinding framework that can use C# and Lua to develop games
MIT License
1.86k stars 363 forks source link

Any reason to implement IServiceBundle or extend AbstractServiceBundle? #20

Closed heshuimu closed 3 years ago

heshuimu commented 3 years ago

This is not a feature request. I just would like to know how your architecture approaches my problem.

I have some components attached to a GameObject prefab that I would like to use as services. While I know that I can use Resources.Load to load and instantiate the prefab synchronously, I want to use LoadAsync and then make the Start method of the service bundle async instead to that I can emphasize that it is a relatively heavy operation.

Because of this, I cannot make my service bundle class conform to IServiceBundle. But since I did not see any methods that would take the interface as a parameter, I am not even sure if I lose any functionality if I don't extend the interface. Is IServiceBundle used just for conventional/ceremonial purpose to remind implementors to follow Start/Stop procedures?

Thank you so much!

vovgou commented 3 years ago

Hi,IServiceBundle cannot solve your needs, it is just a service container similar to IoC/DI. You can use Addressable Asset System or Loxodon.Framework.Bundle to load assets asynchronously.

Can you speak Chinese? If you have QQ, please add my QQ group 622321589

heshuimu commented 3 years ago

Hi,IServiceBundle cannot solve your needs, it is just a service container similar to IoC/DI.

I think I am now aware of that. But, it seems to me that I can make a service bundle class that does not implement the interface and can still properly set up and tear down services. My sense is that I would not lose any extra functionalities if I don't implement the interface, but I wanted to confirm.

Here's what I ended up with:

using UnityEngine;
using Loxodon.Framework.Services;
using Loxodon.Framework.Asynchronous;

#nullable enable

// Does not implement IServiceBundle
public class GameDriverServiceBundle
{
    private readonly IServiceContainer serviceContainer;

    public GameDriverServiceBundle(IServiceContainer serviceContainer)
    {
        this.serviceContainer = serviceContainer;
    }

    public async Task Start()
    {
        GameObject? original = await LoadAsync<GameObject>("GameDriverSupportingComponents");
        GameObject newInstance = Object.Instantiate(original!);

        // Set up example:
        serviceContainer.Register("GameCamera", newInstance.GetComponentInChildren<Camera>());
    }

    public void Stop()
    {
        // Tear down
        serviceContainer.Unregister("GameCamera");
    }

    private static async Task<T?> LoadAsync<T>(string path) where T : Object
    {
        return await Resources.LoadAsync<T>(path) as T;
    }
}
vovgou commented 3 years ago

Yes, you are right.

But please do not store GameObject in ServiceContainer, it is an IoC container, storing business logic services or basic components in the container, such as network components, role backpack services, etc.

Maybe you can store your game object in PlayerContext or ApplicationContext.