获取对调用方法的对象的引用?

时间:2013-02-13 23:50:46

标签: c# .net-4.0

我有一个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中加载,使用反射来确保它有一个Module的子,为它分配一个ID并运行ModuleStart。然后,MyModule可以执行它所需的操作,从第一个dll调用函数以访问内部受保护的内存,但是当调用这些函数时,它们需要知道调用它们的模块的ID。这可能吗? MyModule不知道它的ID,也没有改变它的能力。

3 个答案:

答案 0 :(得分: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);
}

答案 1 :(得分:1)

有些人建议使用调用堆栈来获取模块信息。如果你想获得进行调用的对象的类型,那也不算太糟糕。遗憾的是,没有可行的(即:简单,可移植和功能)方法从调用堆栈中的数据中提取实例信息。有几个原因,包括优化内联方法的问题,然后在堆栈上没有显示...这也会干扰调用类型检测。

鉴于这一事实,简短的回答是你必须提供一个Module对象作为你在DLL中调用的方法的参数。 @ p.s.w.g建议的方法是实现此目的的一种方法,但其缺点是可能污染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();
    }
}

这封装了DLL公开的方法,而不会过多地污染Module类层次结构的符号空间。

[意见类型=“我的”值=“YMMV”]

但是,我建议你认真考虑使用这种类型的抽象。如果您调用的方法需要有关调用它们的特定Module实例的一些信息,则应该在方法的参数中清楚。鼓励您的团队遵循导致清晰度的指导方针比找到抽象小细节的方法更重要。

[/意见]

答案 2 :(得分: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类分开,因为你经常添加新函数。您可以使用extension methods执行几乎完全相同的操作来保持外观不传递任何参数:

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
   }
}
相关问题