2016-11-27 31 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; 
    } 
}