sharp - sobreescribir una propiedad c#
Esconder miembros heredados (8)
Anularlos como Michael sugiere above 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.
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. Conozco ICustomTypeDescriptor
e 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 oculten con el new
operador. (Lo sé, es ridículo)
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.
Para ocultar completamente y marcar para no usar, incluido 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)]
Probé todas las soluciones propuestas y realmente no ocultan nuevos miembros.
Pero este HACE:
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public new string MyHiddenProperty
{
get { return _myHiddenProperty; }
}
Pero en el código-behide todavía es accesible, así que agregue también el atributo obsoleto
[Obsolete("This property is not supported in this class", true)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public new string MyHiddenProperty
{
get { return _myHiddenProperty; }
}
Puedes usar 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();
}
}
Sé que ha habido varias respuestas a esto, y ahora es bastante viejo, pero el método más simple para hacer esto es simplemente declararlos como new private
.
Considere un ejemplo en el que estoy trabajando actualmente, donde tengo una API que pone a disposición todos los métodos en una DLL de terceros. Tengo que tomar sus métodos, pero quiero usar una propiedad .Net, en lugar de un método "getThisValue" y "setThisValue". Entonces, construyo una segunda clase, heredo la primera, hago una propiedad que usa los métodos get y set, y luego anulo los métodos get y set originales como privados. Todavía están disponibles para cualquiera que quiera construir algo diferente en ellos, pero si solo quieren usar el motor que estoy construyendo, entonces podrán usar propiedades en lugar de métodos.
El uso del método de clase doble elimina cualquier restricción sobre no poder usar la new
declaración para ocultar los miembros. Simplemente no puede usar la override
si los miembros están marcados como virtuales.
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 solo la propiedad está visible en la clase APIUsageClass. La clase APIClass todavía está disponible para las personas que desean extender la API original o usarla de una manera diferente, y APIUsageClass está disponible para aquellos que quieren algo más simple.
En definitiva, lo que haré es hacer que el APIClass sea interno y solo exponer mi clase heredada.
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.
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;
}
}
}