我有一个名为ServiceManager
的简单服务管理器,它有两种方法。 Create()
创建服务实例。 Provide()
返回先前已创建的服务。
我有一个基本的实现,但我想知道是否有更清洁的方式。这是我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
}
}
使用该服务很简单:
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
}
}
我的问题是ServiceManager.Provide()
。从字典中获取项目后,请注意转换为T.这种感觉非常不干净,让我想知道我是否遗漏了一些关于泛型如何在C#中工作的东西。是否有其他/更好的方法来完成我想要完成的任务?
答案 0 :(得分:3)
这里没有什么可以改进的。强制转换是必要的,因为字典值类型是MonoBehaviour
。 您知道它实际上是T
,但编译器并没有。你必须通过施放来告诉你。
你做得很好。
答案 1 :(得分:1)
如果每种类型只有一个实例,那就更好了。考虑一个静态泛型类型
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
,那么这不会起作用。