7

私は以下を含むdllを持っています:

public abstract class Module
{
   internal int ID;

   public abstract void ModuleStart();

}

public void function1() {}
public void function2() {}
//etc...

そして、上記のdllを参照する別のdllがあり、次のものがあります。

class MyModule : Module
{
   public override void ModuleStart()
   {
      function1();

   }

}

私ができるようにしたいのは、 function1 が渡されずに、呼び出しモジュールの ID の値を認識できるようにすることです。これを行う方法はありますか? 基本的に私がやろうとしているのは、メインのモジュール DLL が読み込まれ、2 番目の dll に読み込まれるメソッドが実行され、リフレクションを使用して Module の子があることを確認し、ID を割り当てて ModuleStart を実行することです。その後、MyModule は必要なことを実行し、最初の dll から関数を呼び出して内部保護メモリにアクセスできますが、関数が呼び出されるときは、それらを呼び出したモジュールの ID を知る必要があります。これは可能ですか?MyModule はその ID を認識せず、ID を変更することもできません。

4

3 に答える 3

12

.NET 4.5 では、.NET でこれと同様のことを行う機能がいくつか追加されていますCallerMemberNameAttribute。ドキュメントのサンプルは次のとおりです。

public void TraceMessage(string message,
        [CallerMemberName] string memberName = "",
        [CallerFilePath] string sourceFilePath = "",
        [CallerLineNumber] int sourceLineNumber = 0)
{
    Trace.WriteLine("message: " + message);
    Trace.WriteLine("member name: " + memberName);
    Trace.WriteLine("source file path: " + sourceFilePath);
    Trace.WriteLine("source line number: " + sourceLineNumber);
}
于 2013-02-13T23:59:22.370 に答える
1

モジュール情報を取得するためにコールスタックを使用することを提案した人もいます。呼び出しを行ったオブジェクトのタイプを取得したい場合は、それほど悪くはありません。残念ながら、呼び出しスタック内のデータからインスタンス情報を抽出するための実行可能な(つまり、単純で、移植性があり、機能的な)方法はありません。スタックに表示されない最適化インライン化メソッドの問題など、いくつかの理由があります。これは、呼び出しタイプの検出にも干渉する可能性があります。

この事実を考えると、簡単な答えはModule、DLLで呼び出しているメソッドへのパラメーターとしてオブジェクトを提供する必要があるということです。@pswgによって提案された方法は、これを実現する1つの方法ですが、Moduleクラスのシンボルスペースを汚染する可能性があるという欠点があります。これはModule、提供する関数を公開する保護されたAPIメンバーまたはパブリックAPIメンバーをクラスに実装させることで解決できます。

public abstract class Module
{
    internal int ID;

    public class APIWrapper
    {
        Module module;

        public APIWrapper(Module module)
        {
            this.module = module;
        }

        public void method1() { apiimpl.method1(this.module); }
        public int method2() { return apiimpl.method2(this.module); }
    }

    public readonly APIWrapper API;

    public Module()
    {
        ID = generate_module_identity();
        API = new APIWrapper(this);
    }

    public abstract void ModuleStart();
}

internal static class apiimpl
{
    public static void method1(Module module) { ... }
    public static int method2(Module module) { ... }
}

他の開発者は、次のように使用できます。

class MyModule : Module
{
    public override void ModuleStart()
    {
        API.method1();
    }
}

Moduleこれにより、クラス階層のシンボルスペースを過度に汚染することなく、DLLが公開するメソッドがカプセル化されます。

[意見type="my" value = "YMMV"]

ただし、このタイプの抽象化の使用を真剣に再検討することをお勧めします。Module呼び出しているメソッドが、それらを呼び出している特定のインスタンスに関する情報を必要とする場合は、メソッドのパラメーターで明確にする必要があります。明確にするためのガイドラインに従うようにチームを促すことは、細部を抽象化する方法を見つけることよりも重要な場合があります。

[/意見]

于 2013-02-14T03:13:41.863 に答える
0

ID引数を に渡さずに、実行時にを取得することだけが本当に必要な場合はfunction1、継承されたメソッドを使用できます。

public abstract class Module
{
    internal int ID;
    public abstract void ModuleStart();

    protected void function1()
    {
        System.Console.WriteLine ("function1 called from module {0}", this.ID);
    }
}

次に、他のモジュールからの呼び出しは、function1次のように単純に見えます。

class MyModule : Module
{
   public override void ModuleStart()
   {
      this.function1();    // the 'this.' is not required
   }
}

Moduleただし、定期的に新しい関数を追加しているため、これらの関数をクラスから分離したいというコメントから理解できます。拡張メソッドを使用して、パラメーターを渡さない外観を維持することで、ほぼ同じことを行うことができます。

public abstract class Module
{
   internal int ID;
   public abstract void ModuleStart();
}

public static class ModuleExtensions
{
   public static void function1(this Module module)
   {
       innerFunction1(module.ID);
   }

   internal static void innerFunction1(int ID)
   {
        System.Console.WriteLine ("function1 called from module {0}", ID);
   }
}

次に、他のモジュールからの呼び出しは、function1次のように単純に見えます。

class MyModule : Module
{
   public override void ModuleStart()
   {
      this.function1();     // the 'this.' is required
   }
}
于 2013-02-14T00:45:59.157 に答える