Pergunta

Estou procurando uma maneira de ocultar efetivamente os membros herdados.Eu tenho uma biblioteca de classes que herdam de classes base comuns.Algumas das classes descendentes mais recentes herdam propriedades de dependência que se tornaram vestigiais e podem ser um pouco confusas ao usar IntelliSense ou usando as classes em um designer visual.

Essas classes são todos controles escritos para serem compilados para WPF ou Silverlight 2.0.Eu sei sobre ICustomTypeDescriptor e ICustomPropertyProvider, mas tenho certeza de que eles não podem ser usados ​​no Silverlight.

Não é tanto uma questão funcional quanto uma questão de usabilidade.O que devo fazer?

Atualizar

Algumas das propriedades que eu realmente gostaria de ocultar vêm de ancestrais que não são meus e, por causa de uma ferramenta específica para a qual estou projetando, não posso ocultar membros com o new operador.(Eu sei, é ridículo)

Foi útil?

Solução

Substitua-os como Michael sugere acima e para evitar que pessoas usem os métodos substituídos (sp?), marque-os como obsoletos:

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

Se o segundo parâmetro for definido como verdadeiro, um erro do compilador será gerado se alguém tentar chamar esse método e a string no primeiro parâmetro for a mensagem.Se parm2 for falso, apenas um aviso do compilador será gerado.

Outras dicas

Embora você não possa impedir o uso desses membros herdados, você deve ser capaz de ocultá-los do IntelliSense usando o comando EditorBrowsableAttribute:

Using System.ComponentModel;

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

Editar: Acabei de ver isso nos comentários da documentação, o que a torna meio inútil para esse fim:

Há uma nota proeminente que afirma que este atributo "não suprime membros de uma classe na mesma assembleia".Isso é verdade, mas não completo.Na verdade, o atributo não suprime membros de uma classe na mesma solução.

Uma coisa potencial que você pode fazer é conter o objeto em vez de estendê-lo da outra classe.Isso lhe dará maior flexibilidade em termos de expor o que você deseja expor, mas se você realmente precisa que o objeto seja desse tipo, não é a solução ideal (no entanto, você pode expor o objeto a partir de um getter).

Por isso:

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

Torna-se:

public class MyClass
{
    private BaseClass baseClass;

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

Ou:

public class MyClass
{
    private BaseClass baseClass;

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

Acho que a maneira menos hackeada é considerar a composição em vez da herança.

Ou você pode criar uma interface que tenha os membros desejados, fazer com que sua classe derivada implemente essa interface e programe na interface.

Eu sei que houve várias respostas para isso, e já é bastante antigo, mas o método mais simples de fazer isso é simplesmente declará-las como new private.

Considere um exemplo no qual estou trabalhando atualmente, onde tenho uma API que disponibiliza todos os métodos em uma DLL de terceiros.Tenho que pegar os métodos deles, mas quero usar uma propriedade .Net, em vez dos métodos "getThisValue" e "setThisValue".Então, eu construo uma segunda classe, herdo a primeira, crio uma propriedade que usa os métodos get e set e, em seguida, substituo os métodos get e set originais como privados.Eles ainda estão disponíveis para qualquer pessoa que queira construir algo diferente neles, mas se quiserem apenas usar o mecanismo que estou construindo, poderão usar propriedades em vez de métodos.

Usar o método de classe dupla elimina quaisquer restrições de não poder usar o new declaração para ocultar os membros.Você simplesmente não pode usar override se os membros estiverem marcados como virtuais.

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

Agora valueEnum está disponível para ambas as classes, mas apenas a propriedade está visível na classe APIUsageClass.A classe APIClass ainda está disponível para quem deseja estender a API original ou utilizá-la de uma forma diferente, e a APIUsageClass está disponível para quem deseja algo mais simples.

Por fim, o que farei é tornar a APIClass interna e expor apenas minha classe herdada.

Ocultar totalmente e marcar para não usar, incluindo o intellisense que acredito ser o que a maioria dos leitores espera ...

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

Testei todas as soluções propostas e elas não escondem realmente os novos membros.

Mas este FAZ:

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

Mas no code-behide ele ainda está acessível, então adicione também o Atributo Obsoleto

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

Você pode usar uma 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();
        }
    }
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top