it-swarm.com.de

Wie kann ich einen Klassennamen in C # aliasen, ohne dass jeder Datei, die die Klasse verwendet, eine Codezeile hinzugefügt werden muss?

ich möchte einen Alias ​​für einen Klassennamen erstellen. Die folgende Syntax wäre perfekt:

public class LongClassNameOrOneThatContainsVersionsOrDomainSpecificName
{
   ...
}

public class MyName = LongClassNameOrOneThatContainsVersionOrDomainSpecificName;

aber es wird nicht kompiliert.


Beispiel

Hinweis Dieses Beispiel dient nur der Veranschaulichung. Versuchen Sie nicht, dieses spezielle Problem zu lösen, indem Sie vorschlagen, das Design des gesamten Systems zu ändern. Das Vorhandensein oder Fehlen dieses Beispiels ändert nichts an der ursprünglichen Frage.

Ein vorhandener Code hängt vom Vorhandensein einer statischen Klasse ab:

public static class ColorScheme
{
   ...
}

Dieses Farbschema ist das Outlook 2003-Farbschema. Ich möchte ein Outlook 2007-Farbschema unter Beibehaltung des Outlook 2003-Farbschemas einführen:

public static class Outlook2003ColorScheme
{
   ...
}

public static class Outlook2007ColorScheme
{
   ...
}

Aber ich bin immer noch mit der Tatsache konfrontiert, dass der Code vom Vorhandensein einer statischen Klasse namens ColorScheme abhängt. Mein erster Gedanke war, eine ColorScheme-Klasse zu erstellen, die von Outlook 2003 oder Outlook 2007 abstammt:

public static class ColorScheme : Outlook2007ColorScheme
{
}

sie können jedoch nicht von einer statischen Klasse abstammen.

Mein nächster Gedanke war, die statische ColorScheme-Klasse zu erstellen, aber die Outlook2003ColorScheme- und Outlook2007ColorScheme-Klassen nicht statisch zu machen. Dann kann eine statische Variable in der statischen ColorScheme-Klasse auf ein "echtes" Farbschema verweisen:

public static class ColorScheme
{
    private static CustomColorScheme = new Outlook2007ColorScheme();
    ...
}

private class CustomColorScheme 
{ 
   ...
}

private class Outlook2008ColorScheme : CustomColorScheme 
{
    ...
}

private class Outlook2003ColorScheme : CustomColorScheme 
{
   ...
}

dafür müsste ich jedoch eine Klasse, die vollständig aus schreibgeschützten statischen Farben besteht, in überschreibbare Eigenschaften konvertieren. In der ColorScheme-Klasse müssen dann die 30 verschiedenen Eigenschafts-Getter in das enthaltene Objekt eingeteilt werden.

Das ist einfach zu viel Tippen.

Mein nächster Gedanke war also, die Klasse zu aliasisieren:

public static ColorScheme = Outlook2007ColorScheme;

Das lässt sich aber nicht kompilieren.

Wie kann ich eine statische Klasse in einen anderen Namen aliasen?


pdate: Kann jemand bitte die Antwort hinzufügen "Sie können dies nicht in C # tun" , damit ich das als akzeptiert markieren kann Antworten. Jeder, der die Antwort auf dieselbe Frage haben möchte, findet diese Frage, die akzeptierte Antwort und eine Reihe von Problemumgehungen, die möglicherweise hilfreich sind oder auch nicht.

ich möchte diese Frage einfach abschließen.

69
Ian Boyd

Sie können einen Klassennamen in C # nicht aliasen.

Es gibt Dinge, die Sie tun können, um einen Klassennamen in C # nicht als Alias ​​zu kennzeichnen.

Aber um die ursprüngliche Frage zu beantworten: Sie können in C # keinen Aliasnamen für einen Klassennamen verwenden.


pdate: Die Leute sind verwirrt, warum using nicht funktioniert. Beispiel:

Form1.cs

private void button1_Click(object sender, EventArgs e)
{
   this.BackColor = ColorScheme.ApplyColorScheme(this.BackColor);
}

ColorScheme.cs

class ColorScheme
{
    public static Color ApplyColorScheme(Color c) { ... }
}

Und alles funktioniert. Jetzt möchte ich eine new Klasse erstellen und aliasColorScheme dazu (damit kein Code geändert werden muss)):

ColorScheme.cs

using ColorScheme = Outlook2007ColorScheme;

class Outlook2007ColorScheme
{
    public static Color ApplyColorScheme(Color c) { ... }
}

Ohh, es tut mir leid. Dieser Code wird nicht kompiliert:

enter image description here

Meine Frage war, wie man eine Klasse in C # alias. Das geht nicht. Es gibt Dinge, die ich tun kann: nicht Alias ​​eines Klassennamens in C #:

  • ändern Sie stattdessen alle, die von ColorScheme abhängig sind, in usingColorScheme (Umgehung der Codeänderung, da ich keinen Alias ​​verwenden kann).
  • ändern Sie alle, die von ColorScheme abhängig sind, um ein Factory-Muster zu verwenden. Sie müssen eine polymorphe Klasse oder Schnittstelle haben.

Bei diesen Problemumgehungen geht es jedoch darum, vorhandenen Code zu beschädigen. Dies ist keine Option.

Wenn Leute vom Vorhandensein einer ColorScheme - Klasse abhängen, muss ich tatsächlich eine ColorScheme - Klasse kopieren/einfügen.

Mit anderen Worten: Ich kann einen Klassennamen in C # nicht als Alias ​​verwenden.

Dies steht im Gegensatz zu anderen objektorientierten Sprachen, in denen ich den Alias ​​definieren könnte:

ColorScheme = Outlook2007ColorScheme

und ich wäre fertig.

11
Ian Boyd

Wenn Sie den ursprünglichen Klassennamen ändern, können Sie den abhängigen Code mithilfe eines Importalias als typedef -Ersatz umschreiben:

using ColorScheme = The.Fully.Qualified.Namespace.Outlook2007ColorScheme;

Dies muss ganz oben im Datei-/Namespace stehen, genau wie reguläres usings.

Ich weiß jedoch nicht, ob dies in Ihrem Fall praktikabel ist.

110
Konrad Rudolph

Sie können einen Alias ​​für Ihre Klasse erstellen, indem Sie die folgende Codezeile hinzufügen:

using Outlook2007ColorScheme = YourNameSpace.ColorScheme;
21
mohammedn

Sie möchten ein ( Factory | Singleton ), je nach Ihren Anforderungen. Voraussetzung ist, dass der Client-Code nicht weiß, welches Farbschema er erhält. Wenn das Farbschema anwendungsweit sein soll, sollte ein Singleton in Ordnung sein. Wenn Sie unter verschiedenen Umständen ein anderes Schema verwenden, ist wahrscheinlich ein Factory-Muster der richtige Weg. In jedem Fall muss der Code nur an einer Stelle geändert werden, wenn sich das Farbschema ändern muss.

public interface ColorScheme {
    Color TitleBar { get; }
    Color Background{ get; }
    ...
}

public static class ColorSchemeFactory {

    private static ColorScheme scheme = new Outlook2007ColorScheme();

    public static ColorScheme GetColorScheme() { //Add applicable arguments
        return scheme;
    }
}

public class Outlook2003ColorScheme: ColorScheme {
   public Color TitleBar {
       get { return Color.LightBlue; }
   }

    public Color Background {
        get { return Color.Gray; }
    }
}

public class Outlook2007ColorScheme: ColorScheme {
   public Color TitleBar {
       get { return Color.Blue; }
   }

    public Color Background {
        get { return Color.White; }
    }
}
12

versuche dies:

using ColorScheme=[fully qualified].Outlook2007ColorScheme
10
dpurrington

Das Aliasing nach Ihren Wünschen funktioniert in C # nicht. Dies liegt daran, dass das Aliasing über die Anweisung using erfolgt, die auf die betreffende Datei/den betreffenden Namespace beschränkt ist. Wenn Sie 50 Dateien haben, die den alten Klassennamen verwenden, bedeutet dies, dass 50 Stellen aktualisiert werden müssen.

Trotzdem gibt es meiner Meinung nach eine einfache Lösung, um die Codeänderung so gering wie möglich zu halten. Machen Sie die Klasse ColorScheme zu einer Fassade für Ihre Aufrufe der tatsächlichen Klassen mit der Implementierung, und bestimmen Sie anhand der Angabe using in dieser Datei, welche ColorScheme Sie verwenden.

Mit anderen Worten:

using CurrentColorScheme = Outlook2007ColorScheme;
public static class ColorScheme
{
   public static Color ApplyColorScheme(Color c)
   {
       return CurrentColorScheme.ApplyColorScheme(c);
   }
   public static Something DoSomethingElse(Param a, Param b)
   {
       return CurrentColorScheme.DoSomethingElse(a, b);
   }
}

Dann ändern Sie in Ihrem Code dahinter nichts:

private void button1_Click(object sender, EventArgs e)
{
   this.BackColor = ColorScheme.ApplyColorScheme(this.BackColor);
}

Sie können dann die Werte von ColorScheme aktualisieren, indem Sie eine Codezeile aktualisieren (using CurrentColorScheme = Outlook2008ColorScheme;).

Ein paar Bedenken hier:

  • Jede neue Methode oder Eigenschaftsdefinition muss dann an zwei Stellen zur Klasse ColorScheme und zur Klasse Outlook2007ColorScheme Hinzugefügt werden. Dies ist zusätzliche Arbeit, aber wenn es sich um echten Legacy-Code handelt, sollte dies nicht häufig vorkommen. Als Bonus ist der Code in ColorScheme so einfach, dass jeder mögliche Fehler sehr offensichtlich ist.
  • Diese Verwendung statischer Klassen erscheint mir nicht selbstverständlich. Ich würde wahrscheinlich versuchen, den alten Code umzugestalten, um dies anders zu machen, aber ich verstehe auch, dass Ihre Situation das möglicherweise nicht zulässt.
  • Wenn Sie bereits eine ColorScheme -Klasse haben, die Sie ersetzen, kann dieser und jeder andere Ansatz ein Problem darstellen. Ich rate Ihnen, diese Klasse in etwas wie ColorSchemeOld umzubenennen und dann über using CurrentColorScheme = ColorSchemeOld; Darauf zuzugreifen.
4
Timothy

Ich füge diesen Kommentar für Benutzer hinzu, die dies lange nachdem OP ihre "Antwort" akzeptiert hat, finden. Aliasing in C # funktioniert, indem der Klassenname im vollqualifizierten Namespace angegeben wird. Der definierte Aliasname kann innerhalb seines Gültigkeitsbereichs verwendet werden. Beispiel.

using aliasClass = Fully.Qualified.Namespace.Example;
//Example being the class in the Fully.Qualified.Namespace

public class Test{

  public void Test_Function(){

    aliasClass.DoStuff();
    //aliasClass here representing the Example class thus aliasing
    //aliasClass will be in scope for all code in my Test.cs file
  }

}

Entschuldigung für den schnell eingegebenen Code, aber hoffentlich wird erläutert, wie dies implementiert werden sollte, damit die Benutzer nicht irregeführt werden, dass dies in C # nicht möglich ist.

4
J-Americano

Ich nehme an, Sie können immer von der Basisklasse erben, ohne etwas hinzuzufügen

public class Child : MyReallyReallyLongNamedClass {}

[~ # ~] update [~ # ~]

Wenn Sie jedoch die Möglichkeit haben, das class selbst umzugestalten: Ein Klassenname ist normalerweise unnötig lang, da namespaces fehlen.

Wenn Sie Fälle wie ApiLoginUser, DataBaseUser, WebPortalLoginUser sehen, ist dies normalerweise ein Hinweis auf das Fehlen von namespace, da befürchtet wird, dass der Name User könnte in Konflikt geraten.

In diesem Fall können Sie jedoch namespace alias verwenden, wie in den obigen Beiträgen ausgeführt wurde.

using LoginApi = MyCompany.Api.Login;
using AuthDB = MyCompany.DataBase.Auth;
using ViewModels = MyCompany.BananasPortal.Models;

// ...
AuthDB.User dbUser;
using ( var ctxt = new AuthDB.AuthContext() )
{
    dbUser = ctxt.Users.Find(userId);
}

var apiUser = new LoginApi.Models.User {
        Username = dbUser.EmailAddess,
        Password = "*****"
    };

LoginApi.UserSession apiUserSession = await LoginApi.Login(apiUser);
var vm = new ViewModels.User(apiUserSession.User.Details);
return View(vm);

Beachten Sie, dass die class -Namen alle User sind, jedoch in unterschiedlichen namespaces. Zitat PEP-20: Zen of Python :

Namespaces sind eine großartige Idee - machen wir mehr davon!

Hoffe das hilft

3
percebus

Ist es möglich, auf die Verwendung einer Schnittstelle umzusteigen?

Vielleicht könnten Sie eine IColorScheme Schnittstelle erstellen, die alle Klassen implementieren?

Dies würde gut mit dem von Chris Marasti-Georg gezeigten Fabrikmuster funktionieren

2
chills42

Es ist eine sehr späte Teilantwort - aber wenn Sie dieselbe Klasse 'ColorScheme' im selben Namespace 'Outlook', aber in separaten Assemblys, einer mit dem Namen Outlook2003 und der anderen mit dem Namen Outlook2007, definieren, müssen Sie nur auf die entsprechende Assembly verweisen .

0
Mark Farmiloe