【问题标题】:Get the name of the class where the object was created获取创建对象的类的名称
【发布时间】:2013-06-08 06:34:19
【问题描述】:

我有两个类如下:

第一个:

class Class1
 {
     private void Method1()
      {
          var obj=new TestClass();
          obj.TestMethod1();
      }
 }

第二个:

class TestClass
 {
     public void TestMethod1()
      {
           TestMethod2();
      }

      private void TestMethod2()
       {
           //get the calling class 
       }
 }

Class1.Method1 调用TestClass.TestMethod1 进而调用TestClass.TestMethod2 时,我想在TestClass.TestMethod2 中获取Class1 的完全限定类名。我见过这个link,但我想我会得到TestClass.TestMethod1 作为方法名和TestClass 作为类名。如何获取调用类名?

【问题讨论】:

    标签: c# .net reflection


    【解决方案1】:

    没有很好的方法来做到这一点。您可以访问堆栈帧(只需查看 第二个 帧,而不是第一个)-但这既昂贵又脆弱。您可以使用可选的 caller-member-name 属性(从TestMethod1 显式)来获取"Method1",但不能使用"Class1" 部分。另一种选择是显式传入一个对象(或只是名称);例如:

      private void Method1()
      {
          var obj=new TestClass();
          obj.TestMethod1(this);
      }
      public void TestMethod1(object caller=null,
                 [CallerMemberName] string callerName=null)
      {
           TestMethod2(caller??this,callerName??"TestMethod1");
      }
    
      private void TestMethod2(object caller=null,
                 [CallerMemberName] string callerName=null)
      {
          string callerName = ((caller??this).GetType().Name) + "." + callerName
          //get the calling class 
      }
    

    但我不得不承认这很丑

    或许最好先问问为什么你需要这个。

    【讨论】:

    • 其实我的TestClass 是一个实用类,被不同的其他类使用。我想在其调用类的日志文件中记录此 TestClass 中发生的任何异常。需要按照你的建议设计它。
    【解决方案2】:

    你不能通过构造函数将类型传递给第二个类吗:

    class Class1
    {
        private void Method1()
        {
            Type t = typeof(Class1);
            var obj = new TestClass(t);
            obj.TestMethod1();
        }
    }
    
    class TestClass
    {
        private Type _caller;
    
        public TestClass(Type type)
        {
            _caller = type;
        }
        public void TestMethod1()
        {
            TestMethod2();
        }
    
        private void TestMethod2()
        {
            //Do something with the class
        }
    }
    

    【讨论】:

      【解决方案3】:

      您可以查看此代码以找到您的解决方案,而无需传递类实例或类型参数等......:

      class Program
      {
          static void Main(string[] args)
          {
              var c = new Class1();
              c.Method1();
          }
      }
      
      class Class1
      {
          public void Method1()
          {
              var obj = new TestClass();
              obj.TestMethod1();
          }
      }
      
      class TestClass
      {
          public void TestMethod1()
          {
              TestMethod2();
              var mth = new StackTrace().GetFrame(1).GetMethod();
              var clss = mth.ReflectedType.Name;
              Console.WriteLine("Classname in Method1(): {0}", clss);
          }
      
          private void TestMethod2()
          {
              //get the calling class 
              var mth = new StackTrace().GetFrame(1).GetMethod();
              var clss = mth.ReflectedType.Name;
              Console.WriteLine("Class in .Method2(): {0}", clss);
          }
      }
      

      【讨论】:

      • StackTrace 非常昂贵。这可行,但速度几乎是传入Type 的两倍,并且它的使用意图并不那么清楚。基准测试为:0.92003311 ms vs 0.0501211ms 超过 1000000 次迭代。
      • 老实说,它是另一种方法,比使用 IMO 属性或类型参数的杂乱方法签名要干净得多。以性能为代价的可读性,但不要认为性能大到会引起问题。无论如何,它确实回答了这个问题,并展示了完成相同任务的另一种方式。
      • 我强烈反对这更具可读性,但它确实有效。我也不会说采用类型的单个构造函数构成“混乱”,实际上我会说它的意图比这个例子中的要清楚得多。让我们同意不同意:)
      • 哈哈,是的,当我读到“我强烈反对......”时,我想,嗯......可读性可能是一种观点类型的东西。所以,同意:)你提出了一个很好的案例:)
      【解决方案4】:

      这将获得首先调用TestClassType。它打印:

      TestStack.Class1
      TestStack.Program
      

      using System;
      using System.Collections.Generic;
      using System.Linq;
      using System.Text;
      using System.Diagnostics;
      
      namespace TestStack
      {
          class Class1
          {
              public void Method1()
              {
                  var obj = new TestClass();
                  obj.TestMethod1();
              }
          }
      
          class TestClass
          {
              public void TestMethod1()
              {
                  TestMethod2();
              }
      
              private void TestMethod2()
              {
                  StackTrace st = new StackTrace();
                  Type calling = null;
                  foreach (var sf in st.GetFrames())
                  {
                      var type = sf.GetMethod().DeclaringType;
                      if (type != this.GetType())
                      {
                          calling = type;
                          break;
                      }
                  }
                  Console.WriteLine(calling);
              }
          }
          class Program
          {
              static void Main(string[] args)
              {
                  Class1 class1 = new Class1();
                  class1.Method1();
                  TestClass testClass = new TestClass();
                  testClass.TestMethod1();
              }
          }
      }
      

      【讨论】:

        猜你喜欢
        • 2021-08-30
        • 2010-09-24
        • 2023-03-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-02-06
        相关资源
        最近更新 更多