C #: Déterminer le type d'objet dérivé à partir d'une méthode statique de classe de base

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

Question

Dans un programme C #, j’ai une classe de base abstraite avec un "Create" statique. méthode. La méthode Create est utilisée pour créer une instance de la classe et la stocker localement pour une utilisation ultérieure. La classe de base étant abstraite, les objets d'implémentation en dériveront toujours.

Je veux pouvoir dériver un objet de la classe de base, appeler la méthode statique Create (implémentée une fois dans la classe de base) par le biais de la classe dérivée et créer une instance de l'objet dérivé.

Existe-t-il des fonctionnalités dans le langage C # qui me permettent de réaliser cela? Ma position de repli actuelle consiste à transmettre une instance de la classe dérivée en tant qu’un des arguments de la fonction Create, c.-à-d.:

objDerived.Create(new objDerived(), "Arg1", "Arg2");
Était-ce utile?

La solution

Essayez d’utiliser des génériques:

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

Exemple d'utilisation:

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

Autres conseils

Résumé

Il y a deux options principales. Le plus gentil et le plus récent consiste à utiliser des génériques, l'autre à utiliser la réflexion. Je fournis les deux au cas où vous auriez besoin de développer une solution qui fonctionne avant .NET 2.0.

Génériques

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

Où l'utilisation serait:

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

Réflexion

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

Où l'utilisation serait-elle (divisée sur deux lignes pour la lisibilité):

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

Vous souhaitez créer une nouvelle instance de dérivée à partir d'une autre instance de dérivée, en utilisant une méthode de fabrique statique sur la classe de base abstraite? si oui, je me demande pourquoi ... mais ...

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

Est-ce ce que vous voulez?

On dirait que vous devez rendre la méthode Create () abstraite. Et une fois que vous avez fait cela, vous pouvez aussi bien le renommer et en faire le constructeur. Ensuite, vous pouvez avoir une méthode Init () différente que vous appelez après la construction de l'objet si vous en avez besoin, et les effets de polymorphisme normaux gèrent les choses.

Vous ne pouvez pas le faire sans informations extérieures; soit le type de la classe dérivée, une instance de celle-ci, soit le nom complet de la classe dérivée. Tous ces éléments sont équivalents à ce que vous faites déjà. il n'y a pas de meilleure solution à ma connaissance. La nature même des méthodes statiques exclut toute solution plus élégante.

Je ne suis pas sûr de vos objectifs en matière de conception, mais d'après ce que vous avez demandé, il semblerait que cela pourrait aboutir à beaucoup d'odeur de code. Je pense que vous devriez vraiment vous pencher sur les modèles de conception Inversion of Control (IoC) / Injection de dépendance (DI) implémentés dans de nombreux frameworks tels que Microsoft Unity, Castle Windsor, StructureMap, Ninject, Spring.Net, etc.>

Je pense que si vous envisagez d'utiliser un conteneur IoC, votre problème sera résolu de manière beaucoup plus propre et moins couplée.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top