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,运行加载第二个 dll 的方法,使用反射确保它具有模块的子级,为其分配一个 ID 并运行 ModuleStart。然后 MyModule 可以做它需要做的事情,从第一个 dll 调用函数以访问内部受保护的内存,但是当函数被调用时,它们需要知道调用它们的模块的 ID。这可能吗?MyModule 不知道其 ID,也无法更改它。

4

3 回答 3

12

.NET 4.5 添加了一些功能来使用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 建议的方法是实现此目的的一种方法,但缺点是可能会污染Module类的符号空间。这可以通过让Module类实现一个受保护的或公共的 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 公开的方法,而不会对类层次结构的符号空间造成太多污染。

[意见类型=“我的”价值=“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 回答