Вызов статического члена, когда у вас есть только общий параметр

2

Ts там любой способ вызвать статический член по типу, когда у меня есть только общий параметр. Например, если у меня есть что-то вроде этого

public Get<T>(int id)
{
   // I would like to do this
   string s = T.SomeMethodName();
}

Я мог бы сделать это так, но это "yucky", и тогда неважно, статично оно или нет. Или я мог бы использовать отражение, предложенное Юрием.

ISomeKnownInterface i = (ISomeKnownInterface ) new T(); 
string s = i.SomeMethodName();

Итак, теперь вопрос - лучший подход, создающий новый экземпляр использования отражения

public TFormDto Get<TFormDto>(int entityId) where TFormDto : AbstractEntityFormDto, new()
        {
// create new instance
            AbstractEntityFormDto a = (AbstractEntityFormDto) new TFormDto();
            string entityName = a.GetEntityFullTypeName();

// use reflection 

            Type type = typeof(TFormDto);
            string entityName = type.GetMethods(BindingFlags.Public | BindingFlags.Static)
                .Single(m => m.Name == "GetEntityFullTypeName")
                .Invoke(null, null);
Теги:
generics

3 ответа

1
Лучший ответ

Разве это не всегда будет AbstractBaseClass.GetFullName(). В противном случае вы должны использовать отражение на T, чтобы получить статический метод другого класса. Это может быть полезно.

Ниже приведен простой пример:

class TestClass
{
    public static void Hello()
    {

        Console.WriteLine("World!!!");
    }
}

public static void Test<T>() where T : class
{
    Type type = typeof(T);
    type.GetMethods(BindingFlags.Public | BindingFlags.Static)
        .Single(m => m.Name == "Hello")
        .Invoke(null, null);

}     

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

  • 0
    Да, это так. Это осталось от меня, пытаясь определить абстрактную статику, что недопустимо.
  • 0
    Будет ли вызывать метод с помощью такого отражения быстрее, чем просто делать что-то подобное. Это довольно неприятно, чтобы создать его таким образом, но эй, это код фреймворка AbstractEntityFormDto v = (AbstractEntityFormDto) new TFormDto (); строка s = v.EntityFullTypeName;
Показать ещё 2 комментария
1

Проблема не в том, что T имеет статический метод-член с именем SomeMethodName. Если вы хотите позвонить AbstractBaseClass.SomeMethodName, сделайте это. Обоснование того, почему это невозможно, - это расширение методов методов статического интерфейса.

  • 0
    К сожалению, у нас нет ограничения для метода по универсальному параметру. Это решило бы мою проблему.
0

Нет никакого способа сделать это без использования отражения. Чтобы вызвать статический метод, вам всегда нужно указать фактический тип.

Если вы хотите улучшить безопасность кода во время компиляции, вы попытаетесь избежать отражения. Сделайте метод нестатическим и поместите его в интерфейс. Это, скорее всего, (я не знаю, ваша проблема) будет самым чистым решением.

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

interface ISomeInterface
{
  string SomeMethodName();
}

class SomeImplementation : ISomeInterface
{
  public static Instance { get { return new SomeImplementation(); } }

  public string SomeMethodName()
  {
    // implementation of SomeMethodName
  }
}

public Get(ISomeInterface i)
{
   string s = i.SomeMethodName();
}

public Example()
{
  Get(SomeImplementation.Instance);
}

Вы также можете создать новый экземпляр в универсальном методе, вы также можете указать, что вам нужен конструктор по умолчанию:

public Get<T>() where T : ISomeInterface, new()
{
   T instance = new T();
   string s = instance.SomeMethodName();
}

public Example()
{
  Get<SomeImplementation>();
}
  • 0
    Проблема в том, что у меня нет экземпляра, просто общий параметр. Поэтому, в основном, я могу обновить экземпляр и получить значение или использовать отражение.
  • 0
    Разве вы не можете изменить интерфейс вашего метода с помощью универсального параметра?
Показать ещё 5 комментариев

Ещё вопросы

Сообщество Overcoder
Наверх
Меню