Come alias un nome di classe in C #, senza dover aggiungere una riga di codice a ogni file che utilizza la classe?

StackOverflow https://stackoverflow.com/questions/244246

  •  04-07-2019
  •  | 
  •  

Domanda

Voglio creare un alias per un nome di classe. La sintassi seguente sarebbe perfetta:

public class LongClassNameOrOneThatContainsVersionsOrDomainSpecificName
{
   ...
}

public class MyName = LongClassNameOrOneThatContainsVersionOrDomainSpecificName;

ma non verrà compilato.


Esempio

Nota Questo esempio è fornito solo per comodità. Non tentare di risolvere questo particolare problema suggerendo di modificare il design dell'intero sistema. La presenza o la mancanza di questo esempio non modifica la domanda originale.

Alcuni codici esistenti dipendono dalla presenza di una classe statica:

public static class ColorScheme
{
   ...
}

Questa combinazione di colori è la combinazione di colori di Outlook 2003. voglio introdurre una combinazione di colori di Outlook 2007, pur mantenendo la combinazione di colori di Outlook 2003:

public static class Outlook2003ColorScheme
{
   ...
}

public static class Outlook2007ColorScheme
{
   ...
}

Ma sono ancora di fronte al fatto che il codice dipende dalla presenza di una classe statica chiamata ColorScheme. Il mio primo pensiero è stato quello di creare una classe ColorScheme che discenderò da Outlook2003 o Outlook2007:

public static class ColorScheme : Outlook2007ColorScheme
{
}

ma non puoi discendere da una classe statica.

Il mio prossimo pensiero è stato quello di creare la classe ColorScheme statica, ma rendere le classi Outlook2003ColorScheme e Outlook2007ColorScheme non statiche. Quindi una variabile statica nella classe ColorScheme statica può puntare a " true " combinazione di colori:

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

private class CustomColorScheme 
{ 
   ...
}

private class Outlook2008ColorScheme : CustomColorScheme 
{
    ...
}

private class Outlook2003ColorScheme : CustomColorScheme 
{
   ...
}

ma ciò mi richiederebbe di convertire una classe composta interamente da colori di sola lettura statici in proprietà sostituibili, e quindi la mia classe ColorScheme dovrebbe avere i 30 diversi getter di proprietà buttati giù nell'oggetto contenuto.

Questo è solo troppo digitando.

Quindi il mio prossimo pensiero è stato quello di alias la classe:

public static ColorScheme = Outlook2007ColorScheme;

Ma questo non si compila.

Come posso aliasare una classe statica in un altro nome?


Aggiorna: qualcuno può aggiungere la risposta " Non puoi farlo in C # " , quindi posso contrassegnarlo come risposta accettata. Chiunque desideri la risposta alla stessa domanda troverà questa domanda, la risposta accettata e una serie di soluzioni alternative che potrebbero essere utili o meno.

Voglio solo chiudere questa domanda.

È stato utile?

Soluzione 4

Non puoi alias un nome di classe in C #.

Ci sono cose che puoi fare che non stanno aliasando il nome di una classe in C #.

Ma per rispondere alla domanda originale: non puoi alias un nome di classe in C #.


Aggiornamento: le persone sono confuse perché utilizzando non funziona. Esempio:

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) { ... }
}

E tutto funziona. Ora voglio creare una nuova classe e alias ColorScheme (in modo che nessun codice debba essere modificato ):

ColorScheme.cs

using ColorScheme = Outlook2007ColorScheme;

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

Ohh, mi dispiace. Questo codice non viene compilato:

inserisci qui la descrizione dell'immagine

La mia domanda era come alias una classe in C #. Non si può fare. Ci sono cose che posso fare che non sono non alias un nome di classe in C #:

  • cambia invece tutti coloro che dipendono da ColorScheme in usando ColorScheme (modifica del codice alternativa perché non posso alias)
  • cambia tutti coloro che dipendono da ColorScheme per usare un modello di fabbrica in una classe o interfaccia polimorfica (modifica del codice alternativa perché non posso alias)

Ma queste soluzioni alternative comportano la rottura del codice esistente: non un'opzione.

Se le persone dipendono dalla presenza di una classe ColorScheme , devo effettivamente copiare / incollare una classe ColorScheme .

In altre parole: non posso alias un nome di classe in C #.

Questo contrasta con altri linguaggi orientati agli oggetti, dove potrei definire l'alias:

ColorScheme = Outlook2007ColorScheme

e avrei finito.

Altri suggerimenti

Se si modifica il nome della classe originale, è possibile riscrivere il codice dipendente utilizzando un alias di importazione come sostituto typedef :

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

Questo deve andare nella parte superiore del file / spazio dei nomi, proprio come i normali usando s.

Non so se questo sia pratico nel tuo caso, però.

Puoi creare un alias per la tua classe aggiungendo questa riga di codice:

using Outlook2007ColorScheme = YourNameSpace.ColorScheme;

Desideri un ( Factory | Singleton ), a seconda delle tue esigenze. La premessa è di farlo in modo che il codice client non debba sapere quale combinazione di colori sta ottenendo. Se la combinazione di colori dovrebbe essere ampia per l'applicazione, un singleton dovrebbe andare bene. Se è possibile utilizzare uno schema diverso in circostanze diverse, un modello Factory è probabilmente la strada da percorrere. Ad ogni modo, quando la combinazione di colori deve cambiare, il codice deve essere modificato in un solo posto.

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; }
    }
}

prova questo:

using ColorScheme=[fully qualified].Outlook2007ColorScheme

Sto aggiungendo questo commento per gli utenti che lo trovano da molto tempo dopo che OP ha accettato la loro "risposta". L'aliasing in C # funziona specificando il nome della classe usando il suo spazio dei nomi completo. Uno definito, il nome alias può essere utilizzato nel suo ambito. Esempio.

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
  }

}

Ci scusiamo per il codice digitato rapidamente, ma si spera che spieghi come questo dovrebbe essere implementato in modo che gli utenti non inducano in errore a credere che non possa essere fatto in C #.

Alias ??il modo in cui vorresti farlo non funzionerà in C #. Questo perché l'aliasing viene eseguito tramite la direttiva using , che è limitata al file / spazio dei nomi in questione. Se hai 50 file che usano il vecchio nome della classe, ciò significherà 50 posti da aggiornare.

Detto questo, penso che ci sia una soluzione semplice per rendere il tuo codice il più minimo possibile. Rendi la classe ColorScheme una facciata per le tue chiamate alle classi effettive con l'implementazione e usa il utilizzando in quel file per determinare quale ColorScheme tu utilizzare.

In altre parole, fare questo:

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);
   }
}

Quindi, nel tuo codice dietro, non modificare nulla:

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

È quindi possibile aggiornare i valori di ColorScheme aggiornando una riga di codice ( utilizzando CurrentColorScheme = Outlook2008ColorScheme; ).

Un paio di preoccupazioni qui:

  • Ogni nuovo metodo o definizione di proprietà dovrà quindi essere aggiunto in due punti, alla classe ColorScheme e alla classe Outlook2007ColorScheme . Questo è un lavoro extra, ma se questo è un vero codice legacy, non dovrebbe essere un evento frequente. Come bonus, il codice in ColorScheme è così semplice che ogni possibile bug è molto ovvio.
  • Questo uso di classi statiche non mi sembra naturale; Probabilmente proverei a riformattare il codice legacy per farlo diversamente, ma capisco anche che la tua situazione potrebbe non consentirlo.
  • Se hai già una classe ColorScheme che stai sostituendo, questo approccio e qualsiasi altro potrebbero essere un problema. Ti consiglierei di rinominare quella classe in qualcosa come ColorSchemeOld , e poi accedervi tramite usando CurrentColorScheme = ColorSchemeOld; .

Suppongo che tu possa sempre ereditare dalla classe base senza aggiungere nulla

public class Child : MyReallyReallyLongNamedClass {}

UPDATE

Ma se hai la possibilità di refactoring della stessa class : un nome di classe è solitamente inutilmente lungo a causa della mancanza di namespace s.

Se vedi casi come ApiLoginUser , DataBaseUser , WebPortalLoginUser , di solito indica la mancanza di namespace dovuta la paura che il nome User potrebbe essere in conflitto.

In questo caso, tuttavia, puoi utilizzare namespace alias , come è stato sottolineato nei post precedenti

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);

Nota come i nomi class sono tutti User , ma in namespace diversi. Citando PEP-20: Zen of Python :

  

Gli spazi dei nomi sono un'ottima idea per suonare il clacson - facciamolo di più!

Spero che questo aiuti

È possibile passare a utilizzare un'interfaccia?

Forse potresti creare un'interfaccia IColorScheme implementata da tutte le classi?

Funzionerebbe bene con il modello di fabbrica come mostrato da Chris Marasti-Georg

È una risposta parziale molto tardiva, ma se si definisce la stessa classe 'ColorScheme', nello stesso spazio dei nomi 'Outlook', ma in assiemi separati, uno chiamato Outlook2003 e l'altro Outlook2007, tutto ciò che occorre fare è fare riferimento l'assemblea appropriata.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top