Come risolvere questo problema di ereditarietà

1

Ho le seguenti classi:

public abstract class StaticFileController<File, QueryData> : AsyncController
{
     private string _resourceName;

     public StaticFileController(string resourceName)
     {
          _resourceName = resourceName;
     }

     //This method receives _resourceName
     protected virtual void DoSomething(string resource)
     {
         //...
     }
}

public class ScriptController : StaticFileController<FileEntity, ScriptQueryData>
{
     public ScriptController : base("scripts") { }
}

public class StyleController : StaticFileController<FileEntity, StyleQueryData>
{
     public StyleController : base("styles") { }
}

Ora, supponiamo di avere questa classe:

public class ScriptBundleController : ScriptController
{
     protected override void DoSomething(string resource)
     {
         // Use resource name and do something (~50 lines of code)
     }
}

Se voglio creare una classe simile per StyleController , dovrei creare una nuova classe ( con la stessa identica implementazione ):

public class StyleBundleController : StyleController
{
     protected override void DoSomething(string resource)
     {
         // Use resource name and do something (~50 lines of code)
     }
}

Questo mi turba perché sembra che io stia duplicando il codice, che mi darà problemi in futuro.

Come posso risolvere questo problema? Voglio che la mia implementazione sia scritta solo in un posto. Capisco che sarebbero probabilmente necessarie due classi, come ScriptBundleController e StyleBundleController , ma voglio che il metodo DoSomething() sia centralizzato in una sola classe.

    
posta Matias Cicero 29.09.2015 - 21:03
fonte

2 risposte

1

Invece di basare la tua eredità su metodi che sono comuni in questo caso, può avere più senso avere una classe helper esterna che contenga metodi che i Controller possono utilizzare:

public class FileHelper
{
    public YourReturnTypeIfAny Minify(YourParameters params)
    {
        // your minify logic
    }
}

Quindi puoi chiamare Minify() dai tuoi metodi DoSomething() nel tuo StaticFileControllers

    
risposta data 01.10.2015 - 15:31
fonte
0

La risposta è che non puoi fare esattamente questo. Se ci pensi, potresti esporre in modo efficace le variabili private.

dì che possiamo fare qualcosa come:

 public class ScriptBundleController : ScriptController
    {
        protected override void DoSomething(string resource)
        {
            ((BundleController<FileEntity, ScriptQueryData>)this).DoSomething(resource);
        }
    }

riusando l'oggetto a qualcosa al di fuori della sua catena di ereditarietà per poter applicare la nostra nuova funzione DoSomething all'oggetto corrente.

Ma DoSomething in BundleController può accedere alle variabili private di BundleController e quindi a ScriptBundleController e cambiarle, il che è esattamente ciò che l'impostazione dei privati deve fermare!

puoi farlo se cambi la catena di ereditarietà e inserisci BundleController tra i tuoi controller di script / stile e la classe base, passando i tipi generici in basso. Ma questa non è esattamente la stessa funzionalità, perché DoSomething potrebbe essere sovrascritto nei controller di script / stile.

ad es.

public class StyleController : BundleController<FileEntity, StyleQueryData>
{
     public StyleController() : base("styles") { }
}

public class BundleController<T1, T2> : StaticFileController<T1, T2>
{
    public BundleController(string resourceName)
        : base(resourceName)
    { }

    protected override void DoSomething(string resource)
    {
        // Use resource name and do something (~50 lines of code)
    }
}
    
risposta data 01.10.2015 - 15:32
fonte

Leggi altre domande sui tag