2009-04-29 11 views
5

Bellow ist Version des Codes vereinfacht die ich habe:Allgemeine Klasse Fabrik Problem

public interface IControl<T> 
{ 
    T Value { get; } 
} 

public class BoolControl : IControl<bool> 
{ 
    public bool Value 
    { 
     get { return true; } 
    } 
} 

public class StringControl : IControl<string> 
{ 
    public string Value 
    { 
     get { return ""; } 
    } 
} 
public class ControlFactory 
{ 
    public IControl GetControl(string controlType) 
    { 
     switch (controlType) 
     { 
      case "Bool": 
       return new BoolControl(); 
      case "String": 
       return new StringControl(); 
     } 
     return null; 
    } 
} 

Das Problem ist in GetControl Methode der ControlFactory Klasse. Weil es IControl zurückgibt und ich nur IControl < T> habe, ist das eine generische Schnittstelle. Ich kann T nicht liefern, weil es in Bool Fall bool und in String Fall wird es String sein.

Jede Idee, was ich tun muss, damit es funktioniert?

Antwort

5

ableiten Nur IControl<T> von IControl.

public interface IControl<T> : IControl 
{ 
    T Value { get; } 
} 

UPDATE

Wenn ich Sie missunterstood, und Sie nicht wollen, eine nicht-generische Schnittstelle, werden Sie die Methode GetControl() generic, machen.

public IControl<T> GetControl<T>() 
{ 
    if (typeof(T) == typeof(Boolean)) 
    { 
     return new BoolControl(); // Will not compile. 
    } 
    else if (typeof(T) == typeof(String)) 
    { 
     return new StringControl(); // Will not compile. 
    } 
    else 
    { 
     return null; 
    } 
} 

Jetzt haben Sie das Problem, dass die neue Steuerelemente IControl<T> kann nicht implizit gegossen werden und Sie würden dies explizit machen.

public IControl<T> GetControl<T>() 
{ 
    if (typeof(T) == typeof(Boolean)) 
    { 
     return new (IControl<T>)BoolControl(); 
    } 
    else if (typeof(T) == typeof(String)) 
    { 
     return (IControl<T>)new StringControl(); 
    } 
    else 
    { 
     return null; 
    } 
} 

UPDATE

die Besetzung as IControl<T>-(IControl<T>) geändert. Dies wird bevorzugt, da es bei einem Fehler eine Ausnahme verursacht, während as IControl<T> automatisch null zurückgibt.

3
public IControl<T> GetControl<T>() 
{ 
    switch (typeof(T).Name) 
    { 
     case "Bool": 
      return (IControl<T>) new BoolControl(); 
     case "String": 
      return (IControl<T>) new StringControl(); 
    } 
    return null; 
} 

Aktualisierung; ein paar Fehler im Code korrigiert. Heres ein Anruf, um eine Klasse zu bekommen:

IControl<bool> boolControl = GetControl<bool>(); 
+3

@Vadim - Ich würde Ihnen dringend empfehlen, Daniels Lösung zu verwenden, bei der er Typen vergleicht und keine Zeichenfolgen verwendet. Die Verwendung des Namens des Typs ist fehleranfälliger. –

+0

@ Jon B: Sie haben Recht; Durch den Vergleich der Typen wird robusterer Code bereitgestellt. Ich habe Vadims ursprünglichen Code einfach aktualisiert, um zu funktionieren. Daniels Ansatz ist der bessere Weg. –

0

Der Rückgabetyp muss allgemein sein, da, nun, es ist. Denke darüber nach, wie du das verwenden würdest. Die Rückgabe eines stark typisierten Objekts macht eine generische Factory-Methode überflüssig.

Auch wenn Sie es tun könnte, was ist der Gewinn von

IControl<bool> boolControl = controlFactory.GetControl("bool"); 

oder diejenige, die funktionieren würde,

IControl<bool> boolControl = controlFactory.GetControl<bool>("bool"); 

über einen bestimmten

IControl<bool> boolControl = controlFactory.GetBoolControl("bool"); 

So oder so, Sie haben den Schalter() auf der Client-Seite. Entweder ein Objekt zurückgeben oder eine nicht typisierte IControl-Schnittstelle haben.

Verwandte Themen