Esconder miembros heredados

votos
34

Estoy buscando alguna manera de ocultar efectivamente los miembros heredados. Tengo una biblioteca de clases que heredan de clases base comunes. Algunas de las clases descendientes más recientes heredan propiedades de dependencia que se han vuelto vestigiales y pueden ser un poco confusas al usar IntelliSense o al usar las clases en un diseñador visual.

Estas clases son todos los controles que se escriben para ser compilados para WPF o Silverlight 2.0. Lo sé ICustomTypeDescriptory ICustomPropertyProvider, pero estoy bastante seguro de que no se pueden usar en Silverlight.

No es tanto un problema funcional como un problema de usabilidad. ¿Que debería hacer?

Actualizar

Algunas de las propiedades que realmente me gustaría ocultar provienen de antepasados ​​que no son míos y debido a una herramienta específica que estoy diseñando, no puedo hacer que los miembros se escondan con el newoperador. (Lo sé, es ridículo)

Publicado el 04/08/2008 a las 20:13
fuente por usuario
En otros idiomas...                            


8 respuestas

votos
32

Anularlos como Michael sugiere arriba y para evitar que la gente use los métodos anulados (sp?), Márcalos como obsoletos:

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

Si el segundo parm se establece en verdadero, se generará un error de compilación si alguien intenta llamar a ese método y la cadena en el primer parm es el mensaje. Si parm2 es falso, solo se generará una advertencia del compilador.

Respondida el 04/08/2008 a las 21:14
fuente por usuario

votos
16

Si bien no puedes evitar el uso de esos miembros heredados, que yo sepa, deberías poder ocultarlos de IntelliSense usando EditorBrowsableAttribute :

Using System.ComponentModel;

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

Editar: Acabo de ver esto en los comentarios de la documentación, lo que lo hace un poco inútil para este propósito:

Hay una nota destacada que establece que este atributo "no suprime miembros de una clase en el mismo ensamblado". Eso es cierto, pero no completo. En realidad, el atributo no suprime miembros de una clase en la misma solución.

Respondida el 04/08/2008 a las 20:19
fuente por usuario

votos
13

Una cosa potencial que puede hacer es contener el objeto en lugar de extenderlo desde la otra clase. Esto le dará la mayor flexibilidad en términos de exponer lo que quiere exponer, pero si absolutamente necesita que el objeto sea de ese tipo, no es la solución ideal (sin embargo, podría exponer el objeto de un getter).

Así:

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

Se convierte en:

public class MyClass
{
    private BaseClass baseClass;

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

O:

public class MyClass
{
    private BaseClass baseClass;

    public BaseClass BaseClass
    {
        get
        {
            return baseClass;
        }
    }
}
Respondida el 04/08/2008 a las 20:22
fuente por usuario

votos
8

Creo que eres la mejor forma de hackear es considerar la composición en lugar de la herencia.

O bien, podría crear una interfaz que tenga los miembros que desea, hacer que su clase derivada implemente esa interfaz y programar contra la interfaz.

Respondida el 04/08/2008 a las 20:19
fuente por usuario

votos
3

Para ocultar totalmente y marcar a no utilizar, incluyendo IntelliSense que creo que es lo que la mayoría de los lectores esperan ...

[Obsolete("Not applicable in this class.")] 
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
[Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
Respondida el 24/06/2013 a las 20:50
fuente por usuario

votos
3

Sé que ha habido varias respuestas a esta, y es bastante viejo, pero el método más simple de hacer esto es sólo declararlos como new private.

Consideremos un ejemplo actualmente estoy trabajando en, donde tengo una API que pone a disposición de todos los métodos en una tercera parte de DLL. Tengo que tomar sus métodos, pero quiero utilizar una propiedad .Net, en lugar de un método "getThisValue" y "setThisValue". Por lo tanto, voy a construir una segunda clase, heredad el primero, hacer que una propiedad que utiliza los métodos get y establecidos, y luego anular la escapada original y métodos establecidos como privado. Todavía están a disposición de cualquiera que desee construir algo diferente en ellos, pero si lo que quieren es utilizar el motor que estoy construyendo, entonces será capaz de utilizar las propiedades en lugar de métodos.

Utilizando el método de clase doble se deshace de cualquier restricción de no poder utilizar la newdeclaración de ocultar los miembros. Simplemente no se puede utilizar overridesi los miembros están marcados como virtual.

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

Ahora valueEnum está disponible para ambas clases, pero sólo la propiedad es visible en la clase APIUsageClass. La clase APIClass sigue estando disponible para las personas que desean ampliar la API original o utilizarlo de una manera diferente, y el APIUsageClass está disponible para aquellos que quieren algo más sencillo.

En última instancia, lo que voy a hacer es hacer la APIClass interno, y sólo exponer mi clase heredada.

Respondida el 08/12/2010 a las 21:54
fuente por usuario

votos
1

He probado todas las soluciones propuestas y que en realidad no escondo nuevos miembros.

Pero esto se hace:

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

Pero en el código-behide sigue siendo accesible, por lo que añadir Atributo así obsoleto

[Obsolete("This property is not supported in this class", true)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public new string MyHiddenProperty
{ 
    get { return _myHiddenProperty; }
}
Respondida el 23/05/2012 a las 11:19
fuente por usuario

votos
0

Se puede utilizar una interfaz

    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();
        }
    }
Respondida el 12/11/2017 a las 21:24
fuente por usuario

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more