2

誰かが私を正しい方向に向けることができるのだろうか.私はC#にかなり慣れていないので、簡単にやってください.

私のコードは、スマートカード リーダーとのインターフェイス用に提供された API であるアンマネージ DLL を使用しています。DLL を制御することはできません。使いやすくするために C# でラップしたいだけです。これまでのところ、これを行うことができましたが、同じ EntryPoints であるがパラメーターが異なるこの DLL の複数のバージョンをテストする必要があることがわかりました。

ラッパークラスを整理するために、これらの線に沿って何かを試しました。

internal static class UnSafeNativeMethods
{
    internal static class READER
    {
        internal static class SDK20
        {
            [DllImport(dllpath, EntryPoint = "CV_SetCommunicationType")]
            internal static extern int CV_SetCommunicationType(byte type);
            ...
        }

        internal static class SDK21
        {
            [DllImport(dllpath, EntryPoint = "CV_SetCommunicationType")]
            internal static extern int CV_SetCommunicationType(byte type);
            ...
        }
    }
}

しかし、どの呼び出しを使用するかをチェックするときに、非常に見苦しいコードになります。

ReaderSDK sdk = ReaderSDK.SDK20  //Could come from a argument passed in or set in an 
                                 //instantiated class
...
switch (sdk)
{
    case ReaderSDK.SDK20:
        UnSafeNativeMethods.READER.SDK20.CV_SetCommunicationType(0x0);
        break;
    case ReaderSDK.SDK21:
        UnSafeNativeMethods.READER.SDK21.CV_SetCommunicationType(0x0);
        break;
    ...
}

これは私には厄介なようで、誰かが私を正しい方向に向けることができるかどうか疑問に思っています...


編集:以下のコメントを外して、スイッチがまだ残っているため、正しい軌道に乗っているかどうかまだわからないサンプルコードをいくつか思いつきましたが、現在はコンクリートファクトリクラスの一部です。

public enum ConnectionType
{
    RS232 = 0x0,
    USB = 0x1,
    UDP = 0x2
}

interface INativeMethods
{
    string Name();
    void SetCommunicationType(ConnectionType type);
}

class SDK20 : INativeMethods
{
    public string Name()
    {
        return "SDK Version 2.0";
    }

    // Thanks to @dzendras for this!!
    public void SetCommunicationType(ConnectionType type)
    {
        int result = UnSafeNativeMethods.READER.SDK20.CV_SetCommunicationType((byte)type);
        switch (result)
        {
            case 0:
                return;
            case 1:
                throw new NotSupportedException("Communication type not supported");
            case 2:
                throw AnyOtherMeaningfulException("Its message");
        }
    }


}

class SDK21 : INativeMethods
{
    public string Name()
    {
        return "SDK Version 2.1";
    }

    // Thanks to @dzendras for this!!
    public void SetCommunicationType(ConnectionType type)
    {
        int result = UnSafeNativeMethods.READER.SDK21.CV_SetCommunicationType((byte)type);
        switch (result)
        {
            case 0:
                return;
            case 1:
                throw new NotSupportedException("Communication type not supported");
            case 2:
                throw AnyOtherMeaningfulException("Its message");
        }
    }
}

class NativeMethodsFactory
{
    private static NativeMethodsFactory instance = new NativeMethodsFactory();
    private NativeMethodsFactory()
    {

    }

    public static NativeMethodsFactory Instance
    {
         get { return NativeMethodsFactory.instance; }
    }
    public INativeMethods Get(ReaderSDK version)
    {
        switch (version)
        {
            case ReaderSDK.SDK20:
                return new SDK20();

            case ReaderSDK.SDK21:
                return new SDK21();

            default:
                return new SDK20();
        }
    }
}

私はこれで正しい軌道に乗っていますか?

これが、SDKへの呼び出しを実装する方法です...

// sdk passed in as enum, NativeMethods stored as class member.
NativeMethods = NativeMethodsFactory.Instance.Get(sdk);
...
NativeMethods.SetCommunicationType(ConnectionType.USB);
4

2 に答える 2

2

使用パターン 戦略

パターンに関するいくつかのリンク:

http://www.oodesign.com/strategy-pattern.html

戦略パターンの実例

Factoryパターンの助けを借りてStrategyパターンで最終的にどのようになるかのサンプル。

INativeMethods nativeMethods = NativeMethodsFactory.Get(UnsafeSdkVersion.V1);
nativeMethods.CV_SetCommunicationType(aType);

利点:

  1. インターフェイスとファクトリによるデカップリング
  2. スイッチなし
  3. 新しいバージョンを簡単に追加できます。他のすべてのコードは、使用するバージョンに依存しません。
于 2012-06-19T17:57:20.467 に答える
1

マネージド API を変更することをお勧めします。C コードを (DLL から) 呼び出しても、構造パラダイムを使用する必要はありません。ラッパーは完全に客観的でなければなりません。例えば:

internal static extern int CV_SetCommunicationType(byte aType);
  1. 返される int は、成功した場合は 0 であり、その他の値はエラーを示していると思います。void を返し、コードを DLL 呼び出しから例外に内部的に変換します。

    public void SetCommunicationType(byte type) 
    {
         int result = CV_SetCommunicationType(type);
         switch (result)
         {
             case 0:
                 return;
             case 1:
                 throw new NotSupportedException("Communication type not supported");
             case 2:
                 throw AnyOtherMeaningfulException("Its message");
         }
     }
    
  2. aType の列挙型を作成します。

  3. クラスを探します。静的メソッドは純粋な悪です。ドメインを分析し、オブジェクトと動作を探します。たとえば、これは(ばかげた名前、私は知っています...)ConnectionManagerのメソッドである可能性があります。

  4. 契約次第。クラス (異なる SDK 用) にいくつかの共通インターフェイスを実装させます。

  5. メソッドの例で示した方法でハンガリー語表記を使用しないでください。

于 2012-06-20T06:14:40.670 に答える