[英]C# Factory of classes that implement generic Interface
我有一個這樣定義的接口:
public interface IEntitySetMgr<T> {
/// <summary>
/// The columns involved in the query. Only fields in those columns
/// will be retrieved from the db.
/// </summary>
List<ColumnInfo> Columns { get; set; }
/// <summary>
/// The number of entities found in the last query to db.
/// </summary>
int EntityCount { get; }
bool Init();
bool Synch( QueryFilter queryFilter = null );
/// <summary>
/// Retrieves the entities build from data of db.
/// </summary>
ObservableCollection<T> GetEntities();
}
我希望一些類實現該接口,並且希望能夠使用工廠來注冊和創建那些已注冊類的實例。 我有這個Factory,但似乎無法編譯:
public class EntitySetMgrFactory {
public delegate IEntitySetMgr<T> EntitySetMgrCreator<T>();
private Dictionary<string, EntitySetMgrCreator<T>> _creators =
new Dictionary<string, EntitySetMgrCreator<T>>();
private static EntitySetMgrFactory _instance = null;
public static EntitySetMgrFactory Instance {
get {
if( _instance == null ) {
_instance = new EntitySetMgrFactory();
}
return _instance;
}
}
private EntitySetMgrFactory() { }
public bool registerEntitySetMgr<T>( string setName, EntitySetMgrCreator<T> creator ) {
if( !_creators.ContainsKey( setName ) ) {
_creators[setName] = creator;
return true;
}
return false;
}
public IEntitySetMgr<T> getEntitySetMgr<T>( string setName ) {
if( _creators.ContainsKey( setName ) ) {
return (IEntitySetMgr<T>)( _creators[setName] )();
}
return null;
}
}
它抱怨字典的定義。 如果我按字典中的對象更改T,它不會抱怨,但是會在嘗試將EntitySetMgrCreator添加到字典時抱怨,說沒有可用的轉換。 我嘗試顯式地放置演員表,但也不起作用。
我看過一些示例,這些示例使用Activator通過事先知道類型然后強制轉換類型來創建實例,但是我真的想擁有一個創建實例並注冊該方法的方法,這樣我就不必事先了解每種類型。
我已經看到了一些有關協變量的信息,但是我認為這會破壞接口,因為我需要一種返回可觀察到的實體集合的方法。
謝謝你的幫助。
問候,
大衛。
當您編寫此代碼時:
private Dictionary<string, EntitySetMgrCreator<T>> _creators =
new Dictionary<string, EntitySetMgrCreator<T>>();
您實際上沒有T
因為您將類定義為EntitySetMgrFactory
。
您可能必須重新考慮您想怎么做以及您在這里真正想要做什么。 你可以簡單地說
private Dictionary<string, object> _creators =
new Dictionary<string, object>();
然后
public IEntitySetMgr<T> getEntitySetMgr<T>( string setName ) {
if( _creators.ContainsKey( setName ) ) {
return ((EntitySetMgrCreator<T>) _creators[setName] )();
}
return null;
}
但是對我來說,你的目標是什么還不清楚。
該代碼的另一個問題是您的單例實現不是線程安全的。 請檢查以下內容: http : //csharpindepth.com/Articles/General/Singleton.aspx
如果沒有使工廠通用,就無法實現:
EntitySetMgrFactory<T>
並從registerEntitySetMgr
刪除T
要么
制作非通用類型的字典,然后在運行時進行向下轉換。
第一個解決方案:
public class EntitySetMgrFactory<T>
{
public delegate IEntitySetMgr<T> EntitySetMgrCreator<T>();
private readonly Dictionary<string, EntitySetMgrCreator<T>> _creators = new Dictionary<string, EntitySetMgrCreator<T>>();
private static EntitySetMgrFactory<T> _instance;
public static EntitySetMgrFactory<T> Instance => _instance ?? (_instance = new EntitySetMgrFactory<T>());
private EntitySetMgrFactory() { }
public bool registerEntitySetMgr(string setName, EntitySetMgrCreator<T> creator)
{
if (_creators.ContainsKey(setName)) return false;
_creators[setName] = creator;
return true;
}
public IEntitySetMgr<T> getEntitySetMgr<T>(string setName) => _creators.ContainsKey(setName) ? (IEntitySetMgr<T>)_creators[setName]() : null;
}
第二種解決方案:
public class EntitySetMgrFactory
{
public delegate IEntitySetMgr<T> EntitySetMgrCreator<T>();
private readonly Dictionary<string, object> _creators = new Dictionary<string, object>();
private static EntitySetMgrFactory _instance;
public static EntitySetMgrFactory Instance => _instance ?? (_instance = new EntitySetMgrFactory());
private EntitySetMgrFactory() { }
public bool registerEntitySetMgr<T>(string setName, EntitySetMgrCreator<T> creator)
{
if (_creators.ContainsKey(setName)) return false;
_creators[setName] = creator;
return true;
}
public IEntitySetMgr<T> getEntitySetMgr<T>(string setName) => _creators.ContainsKey(setName) ? ((EntitySetMgrCreator<T>)_creators[setName])() : null;
}
不幸的是,這行不通。 您聲明的字典需要 T
的特定類型。 所以Uno已經是對的。 但是我想通用工廠不是您想要的,因為您可能想要一個為不同類型構建通用類的工廠。
因此,我建議使該字典在工廠內部不是通用的,但在外部應保持其類型安全:
public class EntitySetMgrFactory
{
public delegate IEntitySetMgr<T> EntitySetMgrCreator<T>();
private Dictionary<string, object> _creators =
new Dictionary<string, object>();
public bool registerEntitySetMgr<T>(string setName, EntitySetMgrCreator<T> creator)
{
if(_creators.ContainsKey(setName)) return false;
_creators[setName] = creator;
return true;
}
public IEntitySetMgr<T> getEntitySetMgr<T>(string setName)
{
return _creators.ContainsKey(setName)
? (_creators[setName] as EntitySetMgrCreator<T>)?.Invoke()
: null;
}
// shortened for clarity, your constructor etc here...
}
因此,在getEntitySetMgr<T>
我將字典中的object
getEntitySetMgr<T>
回您的委托類型,如果此值不為null
,則調用委托並返回結果。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.