2017-04-09 2 views
0

Ich habe 2 generische Klassen: eine ManagerBase-Klasse und eine ChildBase-Klasse. Sie sind beide abstrakt und sollen konkret gemacht werden. ManagerBase hat eine Liste von ChildBase, weshalb ich es generisch machen möchte, so dass ein CatalogManager: ManagerBase eine Liste von Katalogen hätte. Außerdem hätte jeder Katalog einen Verweis auf seinen Manager - CatalogManager.C# kreisförmige generische Typparameter

public class ManagerBase<T1> : ChildBase<???> 
{ 
    public ManagerBase() 
    { 
     ChildObjects = new List<T1>(); 
    } 

    public List<T1> ChildObjects { get; set; } 
} 

public class ChildBase<T1> : ManagerBase<???> 
{ 
    public ChildBase(T1 parentMgr) 
    { 
     ParentMgr = parentMgr; 
     ParentMgr.ChildObjects.Add(this); 
    } 

    public T1 ParentMgr { get; set; } 
} 

Wie kann ich dieses Objektmodell auflösen?

Danke.

+0

'public class ManagerBase wo TManager: ManagerBase wo TChild: ChildBase ', 'public class ChildBase wobei TManager: ManagerBase wobei TChild: ChildBase ', ', 'class Katalog: ChildBase '. – PetSerAl

Antwort

1

Sie haben die Basisklassen mit dem „merkwürdig rekursive“ Muster zu definieren:

public class ManagerBase<M, T1> 
    where M : ManagerBase<M, T1> 
    where T1 : ChildBase<M, T1> 
{ 
    public ManagerBase() 
    { 
     ChildObjects = new List<T1>(); 
    } 

    public List<T1> ChildObjects { get; set; } 
} 

public class ChildBase<T1, C> 
    where T1 : ManagerBase<T1, C> 
    where C : ChildBase<T1, C> 
{ 
    public ChildBase(T1 parentMgr) 
    { 
     ParentMgr = parentMgr; 
     ParentMgr.ChildObjects.Add((C)(object)this); 
    } 

    public T1 ParentMgr { get; set; } 
} 

Bitte beachten Sie, ich mit Ihrer Nutzung von T1 stecken haben, aber ich denke, das ist ein bisschen verwirrend. Ich hätte gerne M und C für jeden verwendet.

Der Hauptnachteil dabei ist, dass Sie die böse Double Cast von (C)(object)this verwenden müssen, um diese Arbeit zu machen. C# erlaubt keine vollständige Typsicherheit in diesem Muster. Ein ruchloser Entwickler kann untergeordnete Klassen erstellen, die das Muster unterbrechen können.

Dann können die konkreten Klassen sein:

public class CatalogManager : ManagerBase<CatalogManager, Catalog> 
{ 
} 

public class Catalog : ChildBase<CatalogManager, Catalog> 
{ 
    public Catalog(CatalogManager parentMgr) : base(parentMgr) 
    { 
    } 
} 
Verwandte Themen