Получить имена методов интерфейса, строго типизированных - PullRequest
4 голосов
/ 23 февраля 2012

У меня есть интерфейс, подобный этому примеру:

Interface IRequest{

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

Теперь в некоторых компонентах журналирования у меня нет доступа к объекту, реализующему интерфейс, но я хочу использовать имена методовв интерфейсе.я могу, конечно, напечатать их в виде строки (скопировать имя метода в строку), но я хочу использовать их строго типизированные, поэтому мне не нужно синхронизировать имена методов и строки.

Впсевдокод, я бы сделал это:

string s= IRequest.GetProfiles.ToString()

Это возможно каким-то образом?

РЕДАКТИРОВАТЬ:

Может быть, я должен назвать это: использовать интерфейс, как этоEnum string s = IRequest.GetProfiles.ToString ()

Ответы [ 5 ]

6 голосов
/ 23 февраля 2012

Вы можете достичь этого двумя способами:

//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 голосов
/ 08 сентября 2015

Иногда вы не знаете имя класса заранее, тогда вы можете использовать:

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

, а затем:

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

Убедитесь, что метод не нулевой и содержит хотя бы один элемент.

1 голос
/ 27 августа 2015

Это лучшее, чего я достиг, 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;
        }
    }
}
1 голос
/ 23 февраля 2012

Ваш вопрос немного сложен для понимания.Я думаю, что вы хотите записать имя класса или метода экземпляра ...

Если вы хотите строгую типизацию, я думаю, вам нужно использовать рефлексию.Конечно, вы можете добавить строковое имя к каждому классу, который может быть зарегистрирован, но это хрупкий код, и кто-то позже возненавидит вас за это.Вы видите этот стиль в языках, которые не всегда легко поддерживают рефлексию, но я бы рекомендовал против этого на языке, подобном 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);
      } 
 }

Этот стекВопрос переполнения может помочь: Как я могу получить методы вызова в C #

На этом веб-сайте есть фрагмент кода, на котором основаны две важные строки: http://www.csharp -примеры.сеть / отражательный вызов-метод-имя /

0 голосов
/ 14 ноября 2018

Вы можете использовать это

nameof (Interface.Method)

это просто

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...