2016-11-27 3 views
0

Я пытаюсь выяснить, как использовать общий делегат для управления моими экземплярами объектов в игровом движке.C# общий делегат для управления экземплярами объектов

Вот некоторые псевдо-код, чтобы показать, что я пытаюсь сделать:

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(); будет выдавать ошибку, но я только отчасти потеряли о том, как добиться того, что я хотеть.

Любые указатели?

ответ

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; 
    } 
} 
Смежные вопросы