5 Stimmen

Generisches Klassenfabrik-Problem

Im Folgenden finden Sie eine vereinfachte Version des Codes, den ich habe:

public interface IControl
{
    T Value { get; }
}

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

public class StringControl : IControl
{
    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 liegt in der GetControl-Methode der ControlFactory-Klasse. Da sie IControl zurückgibt und ich nur IControl habe, das ein generisches Interface ist. Ich kann T nicht angeben, denn im Fall von Bool wird es zu bool und im Fall von String wird es zu string.

Haben Sie eine Idee, was ich tun muss, um es zum Laufen zu bringen?

5voto

Daniel Brückner Punkte 57561

Leiten Sie IControl einfach von IControl ab.

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

UPDATE

Falls ich Sie falsch verstanden habe und Sie keine nicht-generische Schnittstelle möchten, müssen Sie die Methode GetControl() ebenfalls generisch machen.

public IControl GetControl()
{
    if (typeof(T) == typeof(Boolean))
    {
        return new BoolControl(); // Wird nicht kompilieren.
    }
    else if (typeof(T) == typeof(String))
    {
        return new StringControl(); // Wird nicht kompilieren.
    }
    else
    {
        return null;
    }
}

Jetzt haben Sie das Problem, dass die neuen Steuerelemente nicht implizit in IControl umgewandelt werden können und Sie dies explizit machen müssten.

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

UPDATE

Der Cast von as IControl wurde geändert zu (IControl). Dies ist bevorzugt, da es eine Ausnahme verursacht, wenn ein Fehler auftritt, während as IControl stillschweigend null zurückgibt.

3voto

Fredrik Mörk Punkte 151006
public IControl GetControl()
{
    switch (typeof(T).Name)
    {
        case "Bool":
            return (IControl) new BoolControl();
        case "String":
            return (IControl) new StringControl();
    }
    return null;
}

Update; corrected a couple of errors in the code. Hier ist ein Aufruf zum Abrufen einer Klasse:

IControl boolControl = GetControl();

0voto

Stu Punkte 15215

Der Rückgabetyp muss generisch sein, da er es ist. Überlegen Sie, wie Sie dies verwenden würden. Die Rückgabe eines stark typisierten Objekts macht die Notwendigkeit für eine generische Factory-Methode obsolet.

Auch wenn Sie es könnten, was ist der Vorteil von

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

oder, der funktionieren würde,

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

gegenüber einem spezifischen

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

In jedem Fall haben Sie die switch ()-Anweisung auf der Client-Seite. Entweder geben Sie ein Objekt zurück oder haben eine nicht typisierte IControl-Schnittstelle.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X