Domanda

In un programma C #, ho una classe base astratta con un " Crea " statico metodo. Il metodo Create viene utilizzato per creare un'istanza della classe e archiviarla localmente per un uso successivo. Poiché la classe base è astratta, gli oggetti di implementazione ne deriveranno sempre.

Voglio essere in grado di derivare un oggetto dalla classe base, chiamare il metodo statico Create (implementato una volta nella classe base) attraverso la classe derivata e creare un'istanza dell'oggetto derivato.

Ci sono delle strutture nel linguaggio C # che mi permetteranno di farlo. La mia attuale posizione di fallback è passare un'istanza della classe derivata come uno degli argomenti alla funzione Crea, ovvero:

objDerived.Create(new objDerived(), "Arg1", "Arg2");
È stato utile?

Soluzione

Prova a usare generics:

public static BaseClass Create<T>() where T : BaseClass, new()
{
    T newVar = new T();
    // Do something with newVar
    return T;
}

Uso di esempio:

DerivedClass d = BaseClass.Create<DerivedClass>();

Altri suggerimenti

Sommario

Esistono due opzioni principali. Il più bello e nuovo è usare i generici, l'altro è usare la riflessione. Sto fornendo entrambi nel caso in cui sia necessario sviluppare una soluzione che funzioni prima di .NET 2.0.

Generics

abstract class BaseClass
{
  public static BaseClass Create<T>() where T : BaseClass, new()
  {
    return new T();
  }
}

Dove sarebbe l'utilizzo:

DerivedClass derivedInstance = BaseClass.Create<DerivedClass>();

riflessione

abstract class BaseClass
{
  public static BaseClass Create(Type derivedType)
  {
    // Cast will throw at runtime if the created class
    // doesn't derive from BaseClass.
    return (BaseClass)Activator.CreateInstance(derivedType);
  }
}

Dove sarebbe l'uso (diviso in due righe per leggibilità):

DerivedClass derivedClass
    = (DerivedClass)BaseClass.Create(typeof(DerivedClass));

Vuoi creare una nuova istanza di derivata dall'interno di un'altra istanza di derivata, usando un metodo factory statico sulla classe base astratta? in tal caso, mi chiedo perché ... Ma ...

 public abstract class MyBase
 {
    public static T GetNewDerived<T>() where T : MyBase, new()
    {
        return new T();
    }    
 }
 public class DerivedA : MyBase
 {
    public static DerivedA GetNewDerived()
    {
        return GetNewDerived<DerivedA>();
    }
 }

 public class DerivedB : MyBase
 {
    public static DerivedB GetNewDerived()
    {
        return GetNewDerived<DerivedB>();
    }
 }     

È questo quello che vuoi?

Sembra che tu debba rendere astratto il metodo Create (). E una volta fatto, potresti anche rinominarlo e renderlo anche il costruttore. Quindi puoi avere un diverso metodo Init () che chiami dopo che l'oggetto è stato costruito, se necessario, e i normali effetti di polimorfismo gestiranno le cose.

Non puoi farlo senza informazioni esterne; il tipo della classe derivata, un'istanza di essa o il nome completo della classe derivata. Ognuno di questi è equivalente a quello che stai già facendo; non esiste una soluzione migliore di cui sia a conoscenza. La natura stessa dei metodi statici preclude qualcosa di più elegante.

Non sono sicuro di quali siano i tuoi obiettivi di progettazione, ma da quello che hai chiesto sembra che potrebbe finire con un sacco di odore di codice. Penso che dovresti davvero esaminare i modelli di progettazione Inversion of Control (IoC) / Dependency Injection (DI) implementati in numerosi framework come Microsoft Unity, Castle Windsor, StructureMap, Ninject, Spring.Net e così via.

Penso che se guardi usando un contenitore IoC risolverà il tuo problema in un modo molto più pulito e vagamente accoppiato.

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