継承されたメンバーの非表示
-
08-06-2019 - |
質問
継承されたメンバーを効果的に非表示にする方法を探しています。共通の基本クラスを継承するクラスのライブラリがあります。最近の子孫クラスの一部は、痕跡となっている依存関係プロパティを継承しているため、使用時に少し混乱する可能性があります。 インテリセンス またはビジュアル デザイナーでクラスを使用します。
これらのクラスはすべて、WPF または Silverlight 2.0 用にコンパイルされるように記述されたコントロールです。については知っています ICustomTypeDescriptor
そして ICustomPropertyProvider
, しかし、これらは Silverlight では使用できないことは確かです。
それは機能的な問題というよりも、使いやすさの問題です。どうすればいいですか?
アップデート
本当に非表示にしたいプロパティの一部は、自分のものではない祖先に由来しており、私が設計している特定のツールのせいで、 new
オペレーター。(わかっています、それはばかげています)
解決
マイケルが提案するようにそれらをオーバーライドします その上 また、オーバーライドされた (sp?) メソッドを使用できないようにするには、それらのメソッドを廃止済みとしてマークします。
[Obsolete("These are not supported in this class.", true)]
public override void dontcallmeanymore()
{
}
2 番目の parm が true に設定されている場合、誰かがそのメソッドを呼び出そうとすると、最初の parm の文字列がメッセージになるとコンパイラ エラーが生成されます。parm2 が false の場合、コンパイラ警告のみが生成されます。
他のヒント
私の知る限り、これらの継承されたメンバーの使用を防ぐことはできませんが、 EditorBrowsable属性:
Using System.ComponentModel;
[EditorBrowsable(EditorBrowsableState.Never)]
private string MyHiddenString = "Muahahahahahahahaha";
編集: ドキュメントのコメントでこれを見たところ、この目的には役に立たないものになっています。
この属性は「同じアセンブリ内のクラスのメンバーを抑制しない」という顕著な注記があります。それは真実ですが、完全ではありません。実際には、この属性は同じソリューション内のクラスのメンバーを抑制しません。
実行できる可能性の 1 つは、他のクラスから拡張するのではなく、オブジェクトを含めることです。これにより、公開したいものを公開するという点で最も柔軟になりますが、オブジェクトをそのタイプにすることが絶対に必要な場合、これは理想的な解決策ではありません (ただし、ゲッターからオブジェクトを公開することはできます)。
したがって:
public class MyClass : BaseClass
{
// Your stuff here
}
次のようになります:
public class MyClass
{
private BaseClass baseClass;
public void ExposeThisMethod()
{
baseClass.ExposeThisMethod();
}
}
または:
public class MyClass
{
private BaseClass baseClass;
public BaseClass BaseClass
{
get
{
return baseClass;
}
}
}
最もハック的でない方法は、継承ではなく構成を考慮することだと思います。
または、必要なメンバーを持つインターフェイスを作成し、派生クラスにそのインターフェイスを実装させ、インターフェイスに対してプログラムすることもできます。
これに対する答えがいくつかあることは承知していますが、それはもうかなり古いものですが、これを行う最も簡単な方法は、次のように宣言することです。 new private
.
私が現在取り組んでいる例を考えてみましょう。この例では、サードパーティ DLL のすべてのメソッドを利用できるようにする API があります。それらのメソッドを使用する必要がありますが、「getThisValue」メソッドと「setThisValue」メソッドの代わりに .Net プロパティを使用したいと考えています。そこで、2 番目のクラスを構築し、最初のクラスを継承し、get メソッドと set メソッドを使用するプロパティを作成して、元の get メソッドと set メソッドをプライベートとしてオーバーライドします。これらは、別のものを構築したい人は引き続き利用できますが、私が構築しているエンジンを使用したいだけの場合は、メソッドの代わりにプロパティを使用できるようになります。
ダブルクラスメソッドを使用すると、クラスを使用できないという制限がなくなります。 new
メンバーを非表示にする宣言。ただ使えないだけです override
メンバーが仮想としてマークされている場合。
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 は両方のクラスで使用できるようになりましたが、APIUsageClass クラスではプロパティのみが表示されます。APIClass クラスは、元の API を拡張したい場合や、別の方法で使用したい場合に引き続き使用でき、APIUsageClass は、より単純なものを必要とする場合に使用できます。
最終的には、APIClass を内部化し、継承したクラスのみを公開することになります。
ほとんどの読者が期待していると思われるインテリセンスを含め、完全に非表示にし、使用しないようにマークすること...
[Obsolete("Not applicable in this class.")]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
[Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
提案された解決策をすべてテストしましたが、実際には新しいメンバーを隠すものではありませんでした。
しかし、これは次のことを行います。
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public new string MyHiddenProperty
{
get { return _myHiddenProperty; }
}
ただし、code-behide ではまだアクセスできるため、Obsolete 属性も追加します。
[Obsolete("This property is not supported in this class", true)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public new string MyHiddenProperty
{
get { return _myHiddenProperty; }
}
インターフェイスを使用できます
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();
}
}