2014-02-23 40 views
0

我想創建一個使用字典的小類工廠,但是我被困在一個點上,我必須劃分實例的創建並從字典中獲取實例。如何從類型參數創建類實例?

實例化看起來是這樣的:

public void CreateInstance<T>(string id) where T : class, new() 
{ 
    lock (_syncroot) 
    { 
     _internal_dict.Add(id, new T()); 
    } 
} 

它的工作很好,但問題是,我能做些什麼,如果我想實例化一個類東西必須是參數的構造函數?

有沒有解決方案或建築最佳實踐?

+0

檢查任何依賴注入容器。 – zerkms

+0

是否有任何其他約束'T'從任何類型的接口或類派生,或'_internal_dict'只是一個'Dictionary '? –

+1

我有點困惑。你想達到什麼目的?通常,工廠立即返回創建的類型。只有在工廠裏存儲單身人士纔有意義。工廠中的字典通常將類型(即不是實例的類)映射到接口或可能將類型(類)映射到某種類型的密鑰。你的代碼看起來更像是一個存儲庫。 –

回答

0

在我看來,你正在嘗試創建一個對象庫,而不是工廠。對於存儲庫,在將對象添加到存儲庫之前,更容易實例化對象。

repository.Add(key, new SomeType(arg1, arg2)); 

如果要添加到庫中的所有對象從一個共同的類型派生或實現一些常用的接口,那麼簡單地用一個類型Dictionary<TKey, TValue>。例如:

private Dictionary<string, IGameObject> _gameObjects = 
               new Dictionary<string, IGameObject>(); 

_gameObjects.Add("car", new Car(maxSpeed)); 
_gameObjects.Add("monster", new Monster()); 

並與檢索它:

IGameObject obj = _gameObjects(key); 

如果打算存儲完全無關的類型,然後使用由所述類型和可能的標識符的化合物鍵。

public class Repository 
{ 
    private class RepositoryKey 
    { 
     public RepositoryKey(Type type, string key) 
     { 
      this.Type = type; 
      this.Key = key; 
     } 

     public Type Type { get; private set; } 
     public string Key { get; private set; } 

     //TODO: override Equals and GetHashCode. 
    } 

    private Dictionary<RepositoryKey, object> _dict = 
               new Dictionary<RepositoryKey, object>(); 

    public void Add<T>(string key, T obj) 
    { 
     _dict.Add(new RepositoryKey(typeof(T), key), obj); 
    } 

    public Get<T>(string key) 
    { 
     return (T)_dict[new RepositoryKey(typeof(T), key)]; 
    } 
} 

這只是一個簡單的實現,沒有錯誤處理。

var rep = new Repository(); 
rep.Add("slow", new Car(30)); 
rep.Add("fast", new Car(180)); 
rep.Add("left", new Monster(x1, y1)); 
rep.Add("right", new Monster(x2, y2)); 

... 

Car fastCar = rep.Get<Car>("fast"); 
Monster leftMonster = rep.Get<Monster>("left"); 
+0

這是一個非常有用的代碼,非常感謝! – user1692315

0

class以外沒有T的限制,您唯一真正的選擇是使用Activator類的Refelction。

//Still used for the no parameter constructor checking. 
public void CreateInstance<T>(string id) where T : class, new() 
{ 
    lock (_syncroot) 
    { 
     _internal_dict.Add(id, new T()); 
    } 
} 

public void CreateInstance<T>(string id, params object[] args) where T : class 
{ 
    lock (_syncroot) 
    { 
     _internal_dict.Add(id, Activator.CreateInstance(typeof(T), args)); 
    } 
} 

注意,這消除了做編譯時檢查你選擇的<T>類有一個適當的公共構造可以被調用,可能會引發在運行時一個異常的能力,如果沒有構造可以發現。

+0

謝謝,是的,它似乎工作,但我真的不想用這個問題的反思。 – user1692315

+0

如果你不想反射,那麼你需要爲你想要支持的每種類型預先製作工廠類,並且有一個類型爲「Dictionary 」的第二個字典,並且生成這些實例。 –

+0

如何爲具有靜態成員的類創建標記接口以創建特定類型的東西?編譯器不能阻止類在沒有正確的方法的情況下實現接口,並且派生類將被認爲具有可以產生基本類型的工廠,但是如果代碼想要一個'T:IFactory ',派生類型除非它實現產生它自己的類型或從中派生的東西的'IFactory',否則它不會滿足'T'。 – supercat

0

不可能約束一個類型參數,以便它需要一個類具有參數化構造函數。

您可以做的最好的做法是要求類實現具有工廠方法的接口,然後從通用方法內部調用工廠方法。

從 「必要的C#」,第4版:

public class EntityBase<TKey> 
{ 
    public EntityBase(TKey key) 
    { 
     Key = key; 
    } 

    public TKey Key 
    { 
     get {return _key;} 
     set {_key = value;} 
    } 
    private TKey _key; 
} 

public class EntityDictionary<TKey, TValue, TFactory> : 
    Dictionary<TKey, TValue> 
    where TKey : IComparable<T>, IFormattable 
    where TValue : EntityBase<TKey> 
    where TFactory : IEntityFactory<TKey, TValue>, new() 
{ 
    public TValue New(TKey key) 
    { 
     TValue newEntity = new TFactory().CreateNew(key); 
     Add(newEntity.Key, newEntity); 
     return newEntity; 
    } 
} 

public interface IEntityFactory<TKey, TValue> 
{ 
    TValue CreateNew(TKey key); 
} 

EntityDictionary類需要創建EntityBase一個實例,但是這需要一個參數的構造函數。爲了解決這個問題,創建一個實現IEntityFactory<TKey, TValue>的類,該類有一個默認的構造函數。該類將知道如何調用EntityBase構造函數。

+0

你可以給我一個例子如何做到這一點? – user1692315

+0

謝謝,這對我來說似乎很有趣,但我無法清楚地理解它。這個片段中是否有使用示例代碼的地方? – user1692315

相關問題