2009-03-12 1 views
1

ich eine Kundenhierarchie wie so haben:Design-Problem: Vermeidung Kind Objekttyp Hier erhalten Sie Informationen, wenn Aussagen in Präsentationsschicht

abstract class Customer { 
    public virtual string Name { get; set; } 
} 

class HighValueCustomer : Customer { 
    public virtual int MaxSpending { get; set; } 
} 

class SpecialCustomer : Customer { 
    public virtual string Award { get; set; } 
} 

Wenn ich einen Kunden abrufen, würde ich im Web zeigen, wie bilden die Eigenschaften bearbeiten/ändern. Derzeit verwende ich if-Anweisungen, um den Kind-Kundentyp zu finden und die speziellen Eigenschaften anzuzeigen. Gibt es ein Entwurfsmuster (Besucher?) Oder einen besseren Weg, um die "if" -Anweisungen in der Präsentationsebene zu vermeiden? Wie machst du das?

Weitere Informationen: Dies ist eine asp.net-Website mit nHibernate-Backend. Jeder Kundentyp hat sein eigenes Benutzersteuerelement auf der Seite, die ich automatisch laden möchte, wenn der Kundentyp angegeben wird.

Antwort

2

Können Sie Reflektion verwenden, um die Liste der Eigenschaften zu erhalten, die für eine Unterklasse (Instanz) spezifisch sind? (Weniger fehleranfällig.)

Wenn nicht, erstellen Sie eine (virtuelle) Methode, die die speziellen Eigenschaften zurückgibt. (Mehr fehleranfällig!)

Ein Beispiel des letzteren:

abstract class Customer { 
    public virtual string Name { get; set; } 

    public virtual IDictionary<string, object> GetProperties() 
    { 
     var ret = new Dictionary<string, object>(); 
     ret["Name"] = Name; 
     return ret; 
    } 
} 

class HighValueCustomer : Customer { 
    public virtual int MaxSpending { get; set; } 

    public override IDictionary<string, object> GetProperties() 
    { 
     var ret = base.GetProperties(); 
     ret["Max spending"] = MaxSpending; 
     return ret; 
    } 
} 

class SpecialCustomer : Customer { 
    public virtual string Award { get; set; } 

    public override IDictionary<string, object> GetProperties() 
    { 
     var ret = base.GetProperties(); 
     ret["Award"] = Award; 
     return ret; 
    } 
} 

Sie wollen wahrscheinlich Abschnitte erstellen (? fieldset s) auf Ihrer Webseite, wie auch immer, so if würde es ins Spiel kommen, Diese zusätzliche Codierung ist irgendwie lästig und nutzlos.

+0

ich Reflexion zu vermeiden versuchen. Wie würde ich die virtuelle Methode verwenden, um diese Eigenschaften festzulegen? – Mank

+0

@Mank, Reflexion wäre die einfache Antwort. ; P Ich glaube, Sie können sie möglicherweise mit oder etwas einstellen. Nicht sicher. Vielleicht ein einkapselndes Objekt? Ich kenne C# nicht genug, um dir dort zu helfen. – strager

0

Haben Sie so etwas wie dies versucht:

public class Customer<T> 
    where T : Customer<T> 
{ 
    private T subClass; 
    public IDictionary<string, object> GetProperties() 
    { 
     return subClass.GetProperties(); 
    } 
} 

Mit einer Unterklasse von:

public class FinancialCustomer : Customer<FinancialCustomer> 
{ 
} 

Dies ist aus der Spitze von meinem Kopf könnte so nicht funktionieren. Ich habe diese Art von Code in CSLA.NET gesehen. Hier ist der Link zur CSLA.NET-Klasse BusinessBase.cs, die eine ähnliche Definition hat wie oben.

+0

Sehe ich Dinge, oder ist das (erzwungene) unendliche Rekursion? Kunde >>> Vielleicht meinen Sie stattdessen "wo T: Kunde"? – strager

+0

Nein, ich denke, es sollte funktionieren. Zum Beispiel CSLA.NET hat: öffentliche abstrakte Klasse BusinessBase : Core.BusinessBase, Core.ISavable wo T: BusinessBase Siehe hier: http: //www.lhotka.net/cslacvs/viewvc.cgi/Stamm/cslacs/Csla/BusinessBase.cs? view = Markup –

+0

Zum Beispiel: öffentliche Klasse FinancialCustomer: Customer {} sollte kompilieren. –

2

Ich denke, eine sauberere Organisation wäre eine parallele Hierarchie der Anzeigesteuerungen oder Formate zu haben. Verwenden Sie etwas wie das abstrakte Fabrikmuster, um gleichzeitig die Instanz von Customer und von CustomerForm zu erstellen. Zeigen Sie die zurückgegebene CustomerForm-Instanz an, die über die zusätzlichen Eigenschaften und deren Anzeige und Bearbeitung informiert ist.

0

neu:

interface CustomerEdit 
{ 
    void Display(); 
} 

edit:

abstract class Customer { 
    protected CustomerEdit customerEdit; // customers have an object which allows for edit 

    public virtual string Name { get; set; } 
    public void Display() { customerEdit.Display(); } // allow the CustomerEdit implementor to display the UI elements 
} 

// Set customerEdit in constructor, tie with "this" 
class HighValueCustomer : Customer { 
    public virtual int MaxSpending { get; set; } 
} 

// Set customerEdit in constructor, tie with "this" 
class SpecialCustomer : Customer { 
    public virtual string Award { get; set; } 
} 

Nutzung:

Customer whichCouldItBe = GetSomeCustomer(); 
whichCouldItBe.Display(); // shows UI depeneding on the concrete type