c# - type - where t new()




Masquage des membres hérités (6)

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

Ces classes sont toutes les commandes écrites pour être compilées pour WPF ou Silverlight 2.0. Je connais ICustomTypeDescriptor et ICustomPropertyProvider , mais je suis certain que ceux-ci ne peuvent pas être utilisés dans Silverlight.

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

Mettre à jour

Certaines des propriétés que j'aimerais vraiment cacher viennent d'ancêtres qui ne sont pas les miens et à cause d'un outil spécifique pour lequel je conçois, je ne peux pas faire de cachette avec le new opérateur. (Je sais, c'est ridicule)


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

Using System.ComponentModel;

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

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

Il y a une note importante qui stipule que cet attribut "ne supprime pas les membres d'une classe dans le même assemblage". C'est vrai mais pas complet. En fait, l'attribut ne supprime pas les membres d'une classe dans la même solution.


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

Mais celui-ci:

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

Mais dans code-behide c'est toujours accessible, donc ajoutez aussi Attribut Obsolète

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

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

Considérons un exemple sur lequel je travaille actuellement, où j'ai une API qui rend disponibles toutes les méthodes dans une DLL tierce. Je dois prendre leurs méthodes, mais je veux utiliser une propriété .Net, au lieu d'une méthode "getThisValue" et "setThisValue". Donc, je construis une deuxième classe, hérite la première, crée une propriété qui utilise les méthodes get et set, puis substitue les méthodes get et set d'origine comme private. Ils sont toujours disponibles pour quiconque veut construire quelque chose de différent sur eux, mais s'ils veulent juste utiliser le moteur que je construis, ils pourront utiliser des propriétés au lieu de méthodes.

L'utilisation de la méthode de la double classe élimine toute restriction empêchant l'utilisation de la new déclaration pour masquer les membres. Vous ne pouvez 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; }
}

Maintenant valueEnum est 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 différemment, et APIUsageClass est disponible pour ceux qui veulent quelque chose de plus simple.

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


Pour masquer complètement et marquer de ne pas utiliser, y compris intellisense qui je crois est ce que la plupart des lecteurs attendent ...

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

Une chose potentielle que vous pouvez faire est de contenir l'objet plutôt que de s'étendre de l'autre classe. Cela vous donnera la plus grande flexibilité en termes d'exposition de ce que vous voulez 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;
        }
    }
}

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






dependency-properties