【问题标题】:Get the name(s) of interface methods strong typed获取强类型接口方法的名称
【发布时间】:2012-03-13 19:22:16
【问题描述】:

我有一个类似这个例子的界面:

Interface IRequest{

  List<profile> GetProfiles();
  void SetProfile (Profile p);
}

现在,在某些日志记录组件中,我无法访问实现接口的对象,但我想使用接口中方法的名称。 我当然可以将它们键入为字符串(将方法名称复制到字符串中),但我想使用它们是强类型的,所以我不必保持方法名称和字符串同步。

在伪代码中,我会这样做:

string s= IRequest.GetProfiles.ToString()

这在某种程度上可能吗?

编辑:

也许我应该调用它:像使用枚举一样使用接口 字符串 s= IRequest.GetProfiles.ToString()

【问题讨论】:

  • 你在某处确实有一个对象的实例吗?
  • 不确定方法名称的强类型化是什么意思...如何弱类型化或强类型化方法?您是否尝试使用委托?
  • @Paddy。是的,我有一个对象的实例,但不是在日志记录级别。如果我得到它会有帮助吗?
  • @Michel - 那时还没有真正理解你的问题。你需要一个东西的实例才能调用它的方法。也许如果您发布更多的日志记录代码,可能会让事情变得更清楚。
  • 不确定我是否理解正确。也许你正在寻找一个向下的演员。

标签: c# c#-4.0


【解决方案1】:

您可以通过两种方式实现这一目标:

//If you CAN access the instance
var instance = new YourClass(); //instance of class implementing the interface
var interfaces = instance.GetType().GetInterfaces();

//Otherwise get the type of the class
var classType = typeof(YourClass); //Get Type of the class implementing the interface
var interfaces = classType.GetInterfaces()

然后:

foreach(Type iface in interfaces)
{
    var methods = iface.GetMethods();

    foreach(MethodInfo method in methods)
    {        
        var methodName = method.Name;
    }
}

【讨论】:

    【解决方案2】:

    你的问题有点难以理解。我认为您想记录实例类或方法的名称...

    如果你想要强类型,我认为你需要使用反射。您当然可以为每个可以记录的类添加一个字符串名称,但这是脆弱的代码,以后有人会因此而讨厌您。您会在不容易支持反射的语言中看到这种风格,但我建议不要在像 C# 这样的语言中使用这种风格。

    继续寻找解决方案: 您的日志记录方法是从实例内部调用的吗?如果是这样,我们可以使用反射来获取调用方法的名称和许多其他信息。

    如果是,那么这样的事情可能对你有用:

    class MyRequest: IRequest {
        // other interface implementation details omitted
        public void SetProfiles(Profile p) {
          if(HasUglyPicture(p)) {
             MyLogger.LogError(String.Format(
                     "User {0} update attempted with ugly picture", p.UserName)
             throw new Exception("Profile update failed due to ugly picture!");
         }
     }
    
     class MyLogger : ILogger {
          // other logger details omitted
          public void LogError(string errorMsg) {
              // here's where you get the method name 
              // http://www.csharp-examples.net/reflection-calling-method-name/              
              StackTrace stackTrace = new StackTrace();
              MyLogOutputStream.Write(stackTrace.GetFrame(1).GetMethod().Name);
              MyLogOutputStream.WriteLine(errorMsg);
          } 
     }
    

    这个堆栈溢出问题可能会有所帮助: How I can get the calling methods in C#

    这个网站有两个重要行所基于的代码sn-p: http://www.csharp-examples.net/reflection-calling-method-name/

    【讨论】:

      【解决方案3】:

      这是我取得的最好成绩,HTH:

      using System;
      using System.Collections.Generic;
      using System.Runtime.Remoting.Messaging;
      using System.Runtime.Remoting.Proxies;
      
      using Microsoft.VisualStudio.TestTools.UnitTesting;
      
      namespace DotNetSandbox
      {
          // Subject interface to get names from
          interface IRequest
          {
              List<object> GetProfiles();
              void SetProfile(object p);
          }
      
          // Use case / Example:
          [TestClass]
          public class InterfaceNamesTests
          {
              [TestMethod]
              public void InterfaceNamesTest()
              {
                  // Option 1 - Not strongly typed
                  string name = typeof(IRequest).GetMethod("GetProfiles").Name;
                  Console.WriteLine(name);    // OUTPUT: GetProfiles
      
                  // Option 2 - Strongly typed!!
                  var @interface = InterfaceNames<IRequest>.Create();
      
                  Func<List<object>> func = @interface.GetProfiles;
                  var name1 = func.Method.Name;
                  Console.WriteLine(name1);   // OUTPUT: GetProfiles
      
                  Action<object> action = @interface.SetProfile;
                  var name2 = action.Method.Name;
                  Console.WriteLine(name2);   // OUTPUT: SetProfile
      
                  // Other options results with complex/unclear code.
              }
          }
      
          // Helper class
          public class InterfaceNames<T> : RealProxy
          {
              private InterfaceNames() : base(typeof(T)) { }
      
              public static T Create()
              {
                  return (T)new InterfaceNames<T>().GetTransparentProxy();
              }
      
              public override IMessage Invoke(IMessage msg)
              {
                  return null;
              }
          }
      }
      

      【讨论】:

        【解决方案4】:

        有时你不知道类名,那么你可以使用:

        var interfaceType = typeof(InterfaceName);
        var methods = interfaceType.GetMethods();
        

        然后:

        List<String> methodNames = new List<String>();
        foreach(var method in methods)
        {
            methodNames.Add(method.Name);
        }
        

        一定要检查方法是否不为空并且至少包含一个元素。

        【讨论】:

          【解决方案5】:

          你可以用这个

          nameof(Interface.Method)

          很简单

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2012-03-22
            • 1970-01-01
            • 2015-11-25
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2013-01-15
            相关资源
            最近更新 更多