0

ユーザーに機能を公開する一連のプロパティのみを持つ静的ユーティリティクラスを作成したい

たとえば、次のように呼び出すことができます。

Utils.String.GetHexString("Hello World");

また

Utils.Stream.CopyBytes(instream, outstream);

これに例えることができる最も近いものは、UTF8、ASCIIなどのプロパティがあるSystem.Text.Encodingであるため、次のようなものを呼び出すことができます。

Encoding.UTF8.GetBytes("Hello World");

また

Encoding.ASCII.GetBytes("Hello World");

問題は、エンコーディングでは、これがユーザーに公開されている同等のオブジェクト(UTF8Encoder、 )を呼び出すことです。ASCIIEncoder私が欲しいのは、たとえば、プロパティに関連するオブジェクトの可視性なしで、Utilsを介してのみオブジェクトを公開することです

私は呼び出すことができます:

Utils.Stream.CopyStream(instream, outstream);

しかし、私は呼び出すことができませんでした:

StreamUtils.CopyStream(instr, outstr) //This class is only accessible via the Utils class!

これは可能ですか?可能であれば、そうすることは良い習慣になるのでしょうか、それとも悪い習慣になるのでしょうか?

4

5 に答える 5

5

ここにアイデアがあります:

public interface IStreamUtil
{
    void CopyStream(Stream int, Stream out);
}

internal class StreamUtil : IStreamUtil
{
    // Implementation
}

public static class Util
{
    private static IStreamUtil stream = new StreamUtil();
    public static IStreamUtil Stream 
    {
        get { return stream; }
    }
}

しかし、私にとって、これはやや奇妙な習慣です。個人的には、ユーティリティ機能の拡張メソッドを好みます。

inStream.CopyStreamTo(outStream);
myString.GetHexString();

これは、特に拡張メソッドの検出と解決のアルゴリズムを考慮すると、悪いと見なすこともできます。StreamUtil.Copy()ほとんどの場合、古き良きもので十分です。

于 2012-08-03T15:31:06.127 に答える
1

ユーザーが自分のタイプの変数を作成したり、プロパティStreamUtilsから取得した値を割り当てたりするのを防ぐことはできません。Utils.Stream

ただし、2つの解決策があります。

  1. StreamUtilsコンストラクターを作成することで、ユーザーが自分でクラスのインスタンスを作成できないようにすることができますinternal。このように、クラス(同じアセンブリに配置するか、属性Utilsを使用することによって内部アクセスを許可できる)のみがクラスをインスタンス化できますが、ライブラリのユーザーはインスタンスの関数のみを使用できますが、独自のインスタンスを作成することはできません。InternalsVisibleToStreamUtils

  2. 別のアプローチは、パブリックのネストされた静的クラスを使用することです。クラス内で、必要なメソッドを静的メソッドとして提供Utilsするネストされたパブリック静的クラスを宣言できます。Streamこのように、ユーザーは自分のStreamインスタンスをインスタンス化できませんでした(静的であるため)。少なくともC#では、Utils.Stream本当に必要な場合は、ユーザーにメソッドにアクセスするために常に書き込みを強制することもできます。ただし、このアプローチは最初のアプローチほどクリーンではなく、静的クラスをプロパティゲッターなどと交換することにした場合、(少なくともバイナリレベルで)重大な変更が発生することに注意してください。

于 2012-08-03T15:33:47.920 に答える
0

必要なことは可能ですがUtils、クラス自体としてではなく、いくつかの静的ユーティリティクラスを含む名前空間として表示する必要があります。

namespace Utils
{
    public static class String
    {
        public static string GetHexString(string input)
        {
            ...
        }
    }

    public static class Stream
    {
        public static void CopyBytes(System.IO.Stream instream, System.IO.Stream outstream)
        {
            ...
        }
    }
}

これが推奨される方法であるかどうかは、まったく別の問題です。静的ユーティリティクラスが多すぎる場合の問題は、依存性注入を使用して結合を緩めることができないことです。これにより、適切な単体テストを作成することが難しくなる可能性があります。

于 2012-08-03T15:35:40.900 に答える
0

あなたが達成しようとしていることを見て、私は拡張方法を提案し、試み、そして開発します。

拡張メソッドを使用すると、新しい派生型を作成したり、再コンパイルしたり、元の型を変更したりすることなく、既存の型にメソッドを「追加」できます。拡張メソッドは特殊な種類の静的メソッドですが、拡張型のインスタンスメソッドであるかのように呼び出されます。

ここで提供されるハイパーリンクの詳細をお読みください。

于 2012-08-03T15:36:08.873 に答える
0

わかりました、基本的に(少なくともC#では)私が望むものを正確に達成することは不可能です。Utilクラスを介して機能を表示するには、クラスが表示されている必要があります。

私の解決策は、クラス(たとえばStreamUtilsStringUtils)をシングルトンに変換することでした。コンストラクターは内部であるため、構築できません。それらのメソッドは公開されていますが、オブジェクトをアセンブリの外部でインスタンス化できないため、表示することはできません。Utilsクラスは、シングルトンインスタンスを介して機能をユーザーに公開します。

次のことを考慮してください。

class StreamUtils
{
    static StreamUtils instance;

    internal static StreamUtils Instance
    {
        get
        {
            if(instance == null)
            {
                instance = new StreamUtils();
            }
            return instance;
        }
    }

    internal StreamUtils()
    {
    }

    public void CopyStream(Stream input, Stream output)
    {
    }
}

static class Utils
{
    public StreamUtils Stream
    {
        get
        {
             return StreamUtils.Instance;
        }
    }
}
于 2012-08-15T22:12:49.450 に答える