繁体   English   中英

C#通用委托来管理实例化对象

[英]c# generic delegate to manage instantiated objects

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

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

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 (); 会抛出一个错误,但是我对如何实现自己想要的只是迷失了。

有指针吗?

首先,您的委托语法非常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;
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM