Get instance from type and instance dictionary

I have a simple service manager with a name ServiceManagerthat has two methods. Create()creates an instance of the service. Provide()returns the previously created service.

I have a basic implementation that works, but I wonder if there is a cleaner way. This is my main implementation ServiceManager:

public class ServiceManager : MonoBehaviour
{
    private Dictionary<Type, MonoBehaviour> services = new Dictionary<Type, MonoBehaviour>();

    public void Create<T>() where T : MonoBehaviour
    {
        // Create service
        GameObject serviceObject = new GameObject(typeof(T).Name);
        serviceObject.transform.SetParent(transform); // make service GO our child
        T service = serviceObject.AddComponent<T>(); // attach service to GO

        // Register service
        services.Add(typeof(T), service);
    }

    public T Provide<T>() where T : MonoBehaviour
    {
        return (T)services[typeof(T)]; // notice the cast to T here
    }
}

Using the service is simple:

public class ServiceTest : MonoBehaviour
{
    private void Start()
    {
        // Creating services
        ServiceManager services = FindObjectOfType<ServiceManager>();
        services.Create<MapService>();
        services.Create<InteractionService>();
    }

    private void Example()
    {
        // Get a service
        ServiceManager services = FindObjectOfType<ServiceManager>();
        MapService map = services.Provide<MapService>();
        // do whatever you want with map
    }
}

My question is about ServiceManager.Provide(). Note the cast in T after receiving the item from the dictionary. This seems very unclean and makes me wonder if I am missing something about how generics work in C #. Are there other / better ways to do what I'm trying to accomplish?

+6
2

. , - MonoBehaviour. , T, . .

.

+3

, .

using UnityEngine;

public class ServiceManager : MonoBehaviour
{
    // If this T confuses you from the generic T used elsewhere, rename it
    public static Transform T { get; private set; }

    void Awake()
    {
        T = transform;
    }

    public T Provide<T>() where T : MonoBehaviour
    {
        return ServiceMap<T>.service; // no cast required
    }
}

static class ServiceMap<T> where T : MonoBehaviour
{
    public static readonly T service;

    static ServiceMap()
    {
        // Create service
        GameObject serviceObject = new GameObject(typeof(T).Name);
        serviceObject.transform.SetParent(ServiceManager.T); // make service GO our child
        service = serviceObject.AddComponent<T>(); // attach service to GO
    }
}

:

public class ServiceTest : MonoBehaviour
{
    private void Start()
    {
        // no need to Create services
        // They will be created when Provide is first called on them
        // Though if you want them up and running at Start, call Provide
        // on each here.
    }

    private void Example()
    {
        // Get a service
        ServiceManager services = FindObjectOfType<ServiceManager>();
        MapService map = services.Provide<MapService>();
        // do whatever you want with map
    }
}

, ServiceManagers, .

+1

Source: https://habr.com/ru/post/1016682/


All Articles