Question

Je cherche un moyen de masquer efficacement les membres hérités.J'ai une bibliothèque de classes qui héritent des classes de base communes.Certaines des classes descendantes les plus récentes héritent de propriétés de dépendance qui sont devenues vestigiales et peuvent être un peu déroutantes lors de l'utilisation de IntelliSense ou en utilisant les cours dans un concepteur visuel.

Ces classes sont tous des contrôles écrits pour être compilés pour WPF ou Silverlight 2.0.Je sais à propos ICustomTypeDescriptor et ICustomPropertyProvider, mais je suis presque certain qu'ils ne peuvent pas être utilisés dans Silverlight.

Ce n'est pas tant un problème fonctionnel qu'un problème d'utilisabilité.Que dois-je faire?

Mise à jour

Certaines des propriétés que j'aimerais vraiment masquer proviennent d'ancêtres qui ne sont pas les miens et en raison d'un outil spécifique pour lequel je conçois, je ne peux pas masquer les membres avec l'option new opérateur.(je sais, c'est ridicule)

Était-ce utile?

La solution

Remplacez-les comme Michael le suggère au-dessus de et pour empêcher les gens d'utiliser les méthodes remplacées (sp?), marquez-les comme obsolètes :

[Obsolete("These are not supported in this class.", true)]
public override  void dontcallmeanymore()
{
}

Si le deuxième paramètre est défini sur true, une erreur du compilateur sera générée si quelqu'un tente d'appeler cette méthode et que la chaîne du premier paramètre est le message.Si parm2 est faux, seul un avertissement du compilateur sera généré.

Autres conseils

Bien que vous ne puissiez pas empêcher l'utilisation de ces membres hérités à ma connaissance, vous devriez pouvoir les masquer d'IntelliSense à l'aide du ÉditeurBrowsableAttribute:

Using System.ComponentModel;

[EditorBrowsable(EditorBrowsableState.Never)]
private string MyHiddenString = "Muahahahahahahahaha";

Modifier: Je viens de voir ceci dans les commentaires de la documentation, ce qui le rend un peu inutile à cette fin :

Il y a une note importante qui indique que cet attribut "ne supprime pas les membres d'une classe dans la même assemblée".C'est vrai mais ce n'est pas complet.En fait, l’attribut ne supprime pas les membres d’une classe dans la même solution.

Une chose potentielle que vous pouvez faire est de contenir l’objet plutôt que de l’étendre à partir de l’autre classe.Cela vous donnera la plus grande flexibilité en termes d'exposition de ce que vous souhaitez exposer, mais si vous avez absolument besoin que l'objet soit de ce type, ce n'est pas la solution idéale (cependant, vous pouvez exposer l'objet à partir d'un getter).

Ainsi:

public class MyClass : BaseClass
{
    // Your stuff here
}

Devient:

public class MyClass
{
    private BaseClass baseClass;

    public void ExposeThisMethod()
    {
        baseClass.ExposeThisMethod();
    }
}

Ou:

public class MyClass
{
    private BaseClass baseClass;

    public BaseClass BaseClass
    {
        get
        {
            return baseClass;
        }
    }
}

Je pense que le meilleur moyen le moins compliqué est de considérer la composition par opposition à l'héritage.

Vous pouvez également créer une interface contenant les membres souhaités, demander à votre classe dérivée d'implémenter cette interface et de programmer sur l'interface.

Je sais qu'il y a eu plusieurs réponses à cette question, et c'est assez ancien maintenant, mais la méthode la plus simple pour y parvenir est simplement de les déclarer comme new private.

Prenons un exemple sur lequel je travaille actuellement, dans lequel j'ai une API qui rend disponible chaque méthode dans une DLL tierce.Je dois utiliser leurs méthodes, mais je souhaite utiliser une propriété .Net au lieu d'une méthode "getThisValue" et "setThisValue".Ainsi, je construis une deuxième classe, hérite de la première, crée une propriété qui utilise les méthodes get et set, puis remplace les méthodes get et set d'origine comme privées.Ils sont toujours disponibles pour tous ceux qui souhaitent créer quelque chose de différent, mais s'ils souhaitent simplement utiliser le moteur que je construis, ils pourront alors utiliser des propriétés au lieu de méthodes.

L'utilisation de la méthode double classe élimine toute restriction concernant l'impossibilité d'utiliser le new déclaration pour cacher les membres.Vous ne pouvez tout simplement pas utiliser override si les membres sont marqués comme virtuels.

public class APIClass
{
    private static const string DllName = "external.dll";

    [DllImport(DllName)]
    public extern unsafe uint external_setSomething(int x, uint y);

    [DllImport(DllName)]
    public extern unsafe uint external_getSomething(int x, uint* y);

    public enum valueEnum
    {
        On = 0x01000000;
        Off = 0x00000000;
        OnWithOptions = 0x01010000;
        OffWithOptions = 0x00010000;
    }
}

public class APIUsageClass : APIClass
{
    public int Identifier;
    private APIClass m_internalInstance = new APIClass();

    public valueEnum Something
    {
        get
        {
            unsafe
            {
                valueEnum y;
                fixed (valueEnum* yPtr = &y)
                {
                    m_internalInstance.external_getSomething(Identifier, yPtr);
                }
                return y;
            }
        }
        set
        {
            m_internalInstance.external_setSomething(Identifier, value);
        }
    }

    new private uint external_setSomething(int x, float y) { return 0; }
    new private unsafe uint external_getSomething(int x, float* y) { return 0; }
}

valueEnum est désormais disponible pour les deux classes, mais seule la propriété est visible dans la classe APIUsageClass.La classe APIClass est toujours disponible pour les personnes qui souhaitent étendre l'API d'origine ou l'utiliser d'une manière différente, et la classe APIUsageClass est disponible pour ceux qui souhaitent quelque chose de plus simple.

En fin de compte, ce que je vais faire, c'est rendre l'APIClass interne et exposer uniquement ma classe héritée.

Masquer complètement et marquer à ne pas utiliser, y compris IntelliSense, ce qui, je crois, est ce à quoi la plupart des lecteurs s'attendent...

[Obsolete("Not applicable in this class.")] 
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
[Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]

J'ai testé toutes les solutions proposées et elles ne cachent pas vraiment de nouveaux membres.

Mais celui-ci FAIT :

[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public new string MyHiddenProperty
{ 
    get { return _myHiddenProperty; }
}

Mais en code-behide, il est toujours accessible, alors ajoutez également un attribut obsolète

[Obsolete("This property is not supported in this class", true)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public new string MyHiddenProperty
{ 
    get { return _myHiddenProperty; }
}

Vous pouvez utiliser une interface

    public static void Main()
    {
        NoRemoveList<string> testList = ListFactory<string>.NewList();

        testList.Add(" this is ok ");

        // not ok
        //testList.RemoveAt(0);
    }

    public interface NoRemoveList<T>
    {
        T this[int index] { get; }
        int Count { get; }
        void Add(T item);
    }

    public class ListFactory<T>
    {
        private class HiddenList: List<T>, NoRemoveList<T>
        {
            // no access outside
        }

        public static NoRemoveList<T> NewList()
        {
            return new HiddenList();
        }
    }
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top