2010-12-01 10 views
1

Ich habe ein Konzept für ein Framework von Kontrollen, die ich gerne bauen würde. Was diese Idee unterscheidet, ist, dass ich nicht beabsichtige, den "one size fits all" -Ansatz oder den "one control to rule all" -Ansatz zu wählen.Wie erstellt man in C# ein Mix-In-Architektur-Framework?

Als Beispiel, macht Telerik eine sehr schöne Grid-Steuerung, wie auch ComponentOne, Xceed, etc .. Sie sind jedoch alle gigantische Kontrollen mit Hunderten oder Tausenden von Methoden und Eigenschaften, komplexe Objektmodellhiearchien, etc ... Allzu oft sind diese Gitter viel zu viel für das, was Sie brauchen, aber Sie müssen immer noch die herkulische Aufgabe übernehmen, das gesamte Gitter zu lernen, um etwas Einfaches zu tun.

Mein Konzept ist eher eine "mix-in" -Approach. Erstellen Sie ein sehr einfaches Steuerelement, und erstellen Sie dann Funktionen, die Sie der Steuerung "a-la-carte" hinzufügen können. Zum Beispiel haben Sie ein einfaches Raster, und Sie möchten Raster "Abschnitte" mit Kopf- und Fußzeilen für jeden hinzufügen.

Ok, also wo ist das Problem? Die traditionelle Art, so etwas zu tun, ist die Mehrfachvererbung, die von C# nicht unterstützt wird. Auch wenn es das unterstützt, bin ich immer noch der Meinung, dass MI mehr Probleme hinzufügt, als es löst.

Also ich bin SO für Meinungen auf, wie man dieses Problem anzugehen. Wäre MEF eine mögliche Lösung?

EDIT:

Etwas, das mir einfällt, ist, dass es möglich sein könnte, Ausdruck Bäume zu verwenden, um die Steuerung von verschiedenen Ausdrücken zu bauen. Ich müsste noch etwas darüber nachdenken, aber es ist ein interessantes Konzept.

Eine andere mögliche Option könnte ein "Control Generator" sein, der basierend auf den ausgewählten Features eine Assembly generiert. Das scheint komplexer, aber mit T4 könnte managbar sein.

+0

Siehe hier: http://msdn.microsoft.com/en-us/vcsharp/bb625996.aspx –

+0

@ Robert Harvey - ich habe bereits weitgehend abgelehnte Methoden Erweiterung, weil sie nicht wirklich bieten können zusätzlicher Zustand, nur Methoden. Die Technik, auf die Sie verweisen, würde die Implementierung aller zusätzlichen Zustände durch den Endbenutzer erfordern, an denen ich nicht wirklich interessiert bin. –

Antwort

3

Einige Optionen

  1. das Dekorierermuster Betrachten; kleine Objekte, die das Verhalten einer relativ minimalistischen Klasse erweitern, die Sie zur Laufzeit aufbauen können. Das kanonische Beispiel im Dotnet-Framework würde sich um die IO-Ströme herum befinden (z. B. StreamReader/Writer, TextStreamReader/Writer, FileStreamReader/Writer); es ist ziemlich häufig auch in OO UI-Frameworks, mit dem typischen Beispiel etwa wie var window=new HorizontalScrollingWindowDecorator(new VerticalScrollingWindowDecorator(new Window));

  2. Die State, Strategie, Command und Composite-Muster bieten verschiedene Alternativen für den Umgang mit der Zusammensetzung des Verhaltens, ohne viel Kontrollfluss erfordern. Beispielsweise delegieren Sie bestimmte Verhaltenstypen an den aktuellen Zustand Ihres Objekts (einige Ihrer Klassenmethoden rufen grundsätzlich Methoden des aktuellen Objektstatus auf). Sie können das Verhalten auch an Befehlsobjekte delegieren oder komplexe Befehle mithilfe von zusammengesetzten Befehlen erstellen. Die Einzelvererbung führt im Allgemeinen dazu, dass Sie die Komposition von Objekten über die Vererbung favorisieren, und dies sind alles klassische Muster für das Zusammensetzen von Verhalten, die gut mit der Einzelvererbung funktionieren.

  3. Sie können Delegaten für das "Loch in der Mitte" -Muster verwenden, das in der funktionalen Programmierung üblich ist, wenn ein kleines Stück Verhalten von einer bestimmten Instanz implementiert werden muss.

  4. Sie können PostSharp oder ein ähnliches, aspektorientiertes Programmierwerkzeug verwenden, um das Verhalten der Laufzeit oder des Kompilierens zu beeinflussen, besonders nützlich in Fällen, in denen Verhalten von mehreren verschiedenen Klassen benötigt wird Verantwortung dieser Klasse.

1

Ich möchte versuchen zu antworten, ohne zu kommentieren, ob es ein Problem ist, das es zu lösen lohnt.

Ich habe dies nicht für eine Komponente versucht, aber in der Theorie gibt es die Decorator Pattern: Sie könnten zur Laufzeit Plug-Ins hinzufügen, um die Eingabe (Eingabe) und (Bildschirm) des Steuerelements (Tastatur und Maus) abzufangen.

+0

Ich habe darüber nachgedacht, aber wenn Sie Attribute verwenden, um die Dekoration zu implementieren, kann es ziemlich schnell ziemlich hässlich werden, und ich denke, dass die erforderliche Reflexion eine erhebliche Leistungseinbuße bedeuten würde. –

+0

Richtig .. das war mein Gedanke auf MEF. Allerdings kenne ich MEF nicht genug, um zu wissen, ob das praktisch ist. Oder wenn ich meine eigene Code-Injection-Methode entwickeln müsste. –

1

WPF adressiert dies, indem es Ihnen ermöglicht, visuelle Darstellungen von logischen Elementen mit Datenvorlagen zu kombinieren. Anstatt Features zu mischen, um eine neue Control-Klasse zu erstellen, bietet die Control-Klasse selbst Erweiterungspunkte durch die Möglichkeit, Inhalte verschiedener Typen zu integrieren, mit einem reichhaltigen Template-System, um den Inhalt anzuordnen und zu visualisieren.

Mit anderen Worten, es gibt immer noch wohl "eine Kontrolle, um sie alle zu beherrschen", aber die Kontrolle ist ein Skelett und nicht ein vollständig fleischiger Körper. Das Gerüst bietet einen verständlichen Rahmen, in dem Merkmale hinzugefügt werden können, und das Templating-System liefert den Klebstoff für das Ausarbeiten der Teile der Steuerung.

In Bezug auf MEF, was MEF kauft Sie ist Entdeckung und Injektion von Erweiterungscode. Es ist wertvoll, aber nicht direkt auf das Problem, das Sie beschrieben haben. Ihr Problem hat weniger damit zu tun, Code zu entdecken und mehr mit dem Mechanismus zu tun, wie dieser Code zusammengesetzt wird, um ein zusammenhängendes Gesamt-Control zu erstellen. MEF kann hilfreich sein, um etwas vom Kleben durchzuführen, aber es ist ein relativ kleiner Teil des Problems.

+0

Das ist ein guter Einblick in MEF. Danke, ich habe auf einen Kommentar wie diesen gehofft, um mir zu helfen, die brauchbaren Wege der Analyse einzuschränken. –

+0

@Mystere Man, wenn du überhaupt nicht mit WPF gespielt hast, empfehle ich es dir anzuschauen. Selbst wenn Sie nicht planen, es zu verwenden, haben die Designer des Frameworks eine Menge sehr guter Ideen eingearbeitet und klar darüber nachgedacht, wie Sie eine extrem erweiterbare Benutzeroberfläche erstellen können, ohne eine Menge an benutzerdefiniertem Steuercode zu benötigen. Wenn Sie damit spielen, tun Sie sich einen Gefallen und konzentrieren Sie sich auf den XAML, anstatt den VS-Designer zu verwenden. XAML ist eine äußerst mächtige Sprache für die prägnante Beschreibung von Objekten und deren Beziehungen, die sich direkt auf Ihr Problem der Komposition bezieht. –

0

Möchten Sie ein Add-In-Framework dann erstellen? Ich würde Sie definitiv auf Managed Extensibility Framework hinweisen. Kann in .NET 4.0 mit WinForms oder WPF verwendet werden.

2

Persönlich denke ich, Mehrfachvererbung wäre ein schlechter Weg, um diese Art von Design trotzdem zu implementieren. Es scheint, dass Mehrfachvererbung die meiste Zeit ein schlechtes Design ist. Vererbung ist weit zu steif eine Beziehung zwischen Komponenten.

Zusammensetzung ist viel flexibler, in welchem ​​Fall MEF wäre ein sehr guter Ausgangspunkt dafür.

Die Basisklasse für Ihre Steuerelemente wäre ein Container mit Verhaltensweisen - im Wesentlichen ein MEF-Container.

Es bleibt immer noch die Frage, wie andere Klassen mit Ihren Steuerelementen interagieren. Es gibt viele Möglichkeiten. Zum Beispiel Standardschnittstellen auf der Basissteuerung, Messaging oder sogar dynamische Bindung in C# 4.0 verwenden.

+0

Ich stimme dem MI zu. Ich habe nur erwähnt, dass dies der "traditionelle" Weg war, mit dem Problem umzugehen. Vielleicht sollte ich MEF mehr untersuchen. Ich hatte gehofft, dass jemand mit mehr Erfahrung sagen würde, ob diese Analyse nützlich wäre oder nicht. –

+0

Ich habe MEF ziemlich leicht in einer Webanwendung verwendet. Von dem, was ich gesehen habe, würde ich sagen, dass es sehr gut gestaltet ist und eine sehr flexible Verbindung von Komponenten ermöglicht. Sie müssen jedoch darüber nachdenken, wie Sie die Plug-in/Swap-Fähigkeit von MEF mit dem Markup für Ihre Steuerelemente kombinieren möchten. Sie benötigen etwas, um das Markup zu parsen - und dieser Code muss möglicherweise so viel über die Steuerelemente wissen, für die er das Markup für die Analyse verwendet, wodurch die MEF sowieso überflüssig wird. –

0

Wenn Sie in einem Rahmen interessiert sind, die bereits Mixins für eine Referenz, einen Blick auf die Wiederbewegungsrahmen (https://www.re-motion.org/) umgesetzt hat. Es ist erstaunlich, wie einfach Mixins in diesem Framework implementiert werden können.

Das Folgende ist eine Referenzanwendung auf "Hello World" -Ebene.

Mit den von der Webseite heruntergeladenen Baugruppen erstellen Sie in VS2010 eine Klassenbibliothek und eine Konsolenanwendung, in beiden Projekten fügen Sie Referenzen zu den Assemblies remotion.dll und remotion.interfaces.dll hinzu.

using System; 

namespace Domain 
{ 
    public class Person 
    { 
    public Person() 
    { 
    } 
    public Person(Person person) 
    { 
     FirstName = person.FirstName; 
     LastName = person.LastName; 
     BirthDay = person.BirthDay; 
    } 

    public string FirstName { get; set; } 
    public string LastName { get; set; } 
    public DateTime BirthDay { get; set; } 
    } 
} 



using System; 
using Remotion.Mixins; 

namespace Domain 
{ 
    public interface IEmployeeMixin 
    { 
    int Salary { get; set; } 
    DateTime? HireDate { get; set; } 
    } 

    [Extends(typeof(Person))] 
    public class EmployeeMixin : IEmployeeMixin 
    { 
    public int Salary { get; set; } 
    public DateTime? HireDate { get; set;} 
    public EmployeeMixin() 
    { 
     // set default values 
     Salary = 1000; 
     HireDate = DateTime.Now; 
    } 
    } 
} 



using Domain; 
using Remotion.Reflection; 
using Remotion.Mixins; 

namespace ConsoleApp 
{ 
    class Program 
    { 
    static void Main(string[] args) 
    { 
     Person p = new Person(); 
     p.FirstName = "John"; 
     p.LastName = "Doe"; 

     var employee = (IEmployeeMixin)ObjectFactory.Create<Person>(ParamList.Create(p)); 

     System.Console.WriteLine("Fullname: {0}", ((Person)employee).FirstName + " " + ((Person)employee).LastName); 
     System.Console.WriteLine("Salary: {0}", employee.Salary); 

     System.Console.ReadKey(); 
    } 
    } 
} 

auf dieser Referenzimplementierung Basierend sollte es leicht sein, eine Vorstellung zu bekommen, wie diese Mixins in diesem Rahmen umgesetzt werden. Wenn Sie mehr Informationen über dieses Framework (es ist ein komplettes DDD-Entwicklungsframework) oder die Mixins erhalten möchten, zögern Sie nicht zu fragen. Ich kann Ihnen weitere Unterlagen zur Verfügung stellen.

Stefan

+0

Sie können auch https://www.re-motion.org/community ausprobieren –

Verwandte Themen