2012-01-22 9 views
5

Dynamicznie dodaje i zastępuje formanty w panelu WinForm w środowisku wykonawczymW jaki sposób można zastąpić dziedziczenie interfejsami w fabrycznym wzorze?

Mimo że wszystkie prace kazano mi implementować interfejsy zamiast dziedziczenia z baseUserControl.

Jestem wszystkim za to, ale ja nie widzę w jaki sposób można to osiągnąć ten sam efekt przy użyciu interfejsów

Jak bym kodować moja fabryka?

Jak można to poprawić i zamiast tego korzystać z interfejsów?

//Simplified noddy example 

//Client code 
var controlA = ControlFactory 
    .Create("UserControlA") as UserControlA; 

panel1.Controls.Add(ControlA); 

//Factory 
public class ControlFactory 
{ 
    public static BaseUserControl Create(string name) 
    { 
     switch (name) 
     { 
      case "UserControlA": 
       var userControlA = new UserControlA(); 

       return userControlA; 

      case "UserControlB": 
       var userControlB = new UserControlB(); 
       return userControlB; 
     } 
     return null; 
    } 
} 
    //BaseUserControl 
    public partial class BaseUserControl : UserControl 
    { 
     public BaseUserControl() 
     { 
      InitializeComponent(); 
     } 

     public virtual void DoSomething() 
     { 

     } 
    } 

    public partial class UserControlA : BaseUserControl 
    { 
     public UserControlA() 
     { 
      InitializeComponent(); 
     } 

     public override void DoSomething() 
     { 
      //Do something here 
     } 
    } 

public partial class UserControlB : BaseUserControl 
{ 
    public UserControlB() 
    { 
     InitializeComponent(); 
    } 

    public override void DoSomething() 
    { 
     //Do something here 
    } 
} 
+0

wygląda jak pytanie o http://codereview.stackexchange.com/ – GolfWolf

+3

Dlaczego? Jaka byłaby korzyść z używania interfejsów w klasie bazowej? – Oded

+0

Nie są to wyłączne. Twój IUserControl może zadeklarować DoSomething() i możesz zaimplementować BaseControl jako implementację IUserControl (i zwrócić IUserControl z fabryki). – Joe

Odpowiedz

7

Oto w jaki sposób można to zrobić:

using System; 
using System.Windows.Forms; 
using System.ComponentModel; 

//Interface 
public interface IControl : IComponent 
{ 
    void DoSomething(); 
} 

//Factory 
public class ControlFactory 
{ 
    public static IControl Create(string name) 
    { 
     switch (name) 
     { 
      case "UserControlA": 
       var userControlA = new UserControlA(); 

       return userControlA; 

      case "UserControlB": 
       var userControlB = new UserControlB(); 
       return userControlB; 
     } 
     return null; 
    } 
} 

//BaseUserControl 
public partial class BaseUserControl : UserControl, IControl 
{ 
    public BaseUserControl() 
    { 
     InitializeComponent(); 
    } 

    public virtual void DoSomething() 
    { 

    } 
} 

public partial class UserControlA : BaseUserControl, IControl 
{ 
    public UserControlA() 
    { 
     InitializeComponent(); 
    } 

    public override void DoSomething() 
    { 
     //Do something here 
    } 
} 

public partial class UserControlB : BaseUserControl, IControl 
{ 
    public UserControlB() 
    { 
     InitializeComponent(); 
    } 

    public override void DoSomething() 
    { 
     //Do something here 
    } 
} 

Można zachować BaseUserControl jeśli masz jakieś funkcje, które są wspólne dla UserControlA i UserControlB; w przeciwnym razie należy go wyeliminować, a pozostałe dwa wyprowadzić bezpośrednio z UserControl.

Należy należy zdefiniować wszystkich członków, których może potrzebować dostęp z klas pochodnych w ramach interfejsu IControl. Obejmuje to wszystkich członków, których dziedziczy po UserControl. Nie będziesz jednak musiał ponownie wprowadzać ich w swoich konkretnych klasach.

//Interface 
public interface IControl : IComponent 
{ 
    void DoSomething(); 

    // To be inherited from UserControl. 
    Size Size { get; set; } 
    bool Focus(); 
    event EventHandler FontChanged; 
} 

Jeśli trzeba dodać te służą do aplikacji Windows Forms - zazwyczaj jako argument do wywołania Control.ControlCollection.Add metoda - trzeba będzie uzyskać instancję Control odpowiadającą kontrolą. W ramach obecnej implementacji można to osiągnąć po prostu za pomocą castingu; jednak należy to odizolować od konsumentów twojego interfejsu, na wypadek gdyby zdecydowałeś się zmienić podstawową implementację w przyszłości. Tak więc, chciałbym używać:

//Interface 
public interface IControl : IComponent 
{ 
    void DoSomething(); 

    Control AsWindowsForms(); 
} 

//BaseUserControl 
public partial class BaseUserControl : UserControl, IControl 
{ 
    public BaseUserControl() 
    { 
     InitializeComponent(); 
    } 

    public virtual void DoSomething() 
    { 

    } 

    public Control AsWindowsForms() 
    { 
     return this as Control; 
    } 
} 

W kodzie klienta:

var controlA = ControlFactory.Create("UserControlA").AsWindowsForms(); 
var controlB = ControlFactory.Create("UserControlB").AsWindowsForms(); 
panel1.Controls.Add(controlA); 
panel1.Controls.Add(controlB); 
+0

+1 dla wglądu AsWindowsForms() – radarbob

Powiązane problemy