c#generic delegate来管理实例化对象

时间:2016-11-27 01:29:48

标签: c# generics architecture game-engine

我正在试图弄清楚如何使用通用委托来管理游戏引擎中的实例化对象。

这是一些伪代码,用于演示我正在尝试做的事情:

public class ObjectManager
{
    public delegate void ObjectManagerEvent <T> (T instantiatedObject);
    public ObjectManagerEvent <T> onObjectInstantiated;


    public void InstantiateObject (Object objToInstantiate)
    {
        var obj = SomeInternalInstantiateMethod ();

        ObjectManagerEvent _onObjectInstantiated = onObjectInstantiated;
        if (_onObjectInstantiated != null)
        {
            _onObjectInstantiated (obj);
        }
    }
}


public class Shape  : EBehaviour {}
public class Animal : EBehaviour {}


public class DemoShape
{
    private void Init ()
    {
        ObjectManager.onObjectInstantiated += OnObjectInstaniated;
    }

    public void OnObjectInstaniated (Shape shape)
    {
        // do something with shape 
    }
}

public class DemoAnimal
{
    private void Init ()
    {
        ObjectManager.onObjectInstantiated += OnObjectInstaniated;
    }

    public void OnObjectInstaniated (Animal animal)
    {
        // do something with animal 
    }
}

我知道public ObjectManagerEvent <T> onObjectInstantiated ();会引发错误,但我对如何实现我想要的东西感到很遗憾。

任何指针?

1 个答案:

答案 0 :(得分:2)

首先,您的委托语法非常C#1.0。

选项1

您无法以特别简单和优雅的方式执行此操作,因为在C#中,您无法使用开放泛型类型来声明通用事件。我们可以做的最接近的是创建一个对象字典,每个对象都有一个事件,我们可以使用泛型方法来访问这个字典。

我还假设你打算让InstantiateObject创建并返回一个新实例。在这里,我还假设一切都是一个带无参数构造函数的类。

public static class ObjectManager
{
    public class TypeEvent<T>
    {
        // Our event handler will accept a parameter of type T and return void
        public event Action<T> OnObjectInstantiated;

        public void RaiseObjectInstantiated(T obj)
        {
            OnObjectInstantiated?.Invoke(obj);
        }
    }

    private static Dictionary<Type, object> _typeMap = new Dictionary<Type, object>();

    public static TypeEvent<T> ForType<T>() where T: class, new()
    {

        Type t = typeof(T);
        if (!_typeMap.ContainsKey(t))
        {
            _typeMap[t] = new TypeEvent<T>();
        }
        return _typeMap[t] as TypeEvent<T>;

    }

    public static T InstantiateObject<T>() where T: class, new()
    {
        T obj = new T();
        ForType<T>().RaiseObjectInstantiated(obj);
        return obj;
    }
}

您可以像这样使用它:

        ObjectManager.ForType<Foo>().OnObjectInstantiated += fooInstantiated;
        Foo f = ObjectManager.InstantiateObject<Foo>();

选项2

如果您可以将ObjectManager本身设置为静态泛型类,则可以大大简化此操作。请注意,这意味着您不再只有一个ObjectManager类 - ObjectManager<Foo>ObjectManager<Bar>现在是具有不同变量的不同类。如果这对你来说是可以接受的,那么对于你告诉我们ObjectManager需要做的一点点来说,这会让事情变得更加清晰:

public static class ObjectManager<T> where T : class, new()
{
    // Our event handler will accept a parameter of type T and return void
    public static event Action<T> OnObjectInstantiated;

    public static T InstantiateObject() 
    {
        T obj = new T();
        OnObjectInstantiated?.Invoke(obj);
        return obj;
    }
}