Come alias un nome di classe in C #, senza dover aggiungere una riga di codice a ogni file che utilizza la classe?
-
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.
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:
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
inusando
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 classeOutlook2007ColorScheme
. Questo è un lavoro extra, ma se questo è un vero codice legacy, non dovrebbe essere un evento frequente. Come bonus, il codice inColorScheme
è 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 comeColorSchemeOld
, e poi accedervi tramiteusando 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.