Как go из типа среды выполнения (Type) в параметр связанного типа (T)? - PullRequest
0 голосов
/ 01 августа 2020

tl; dr - я десериализую объекты (например, экземпляр «Animal») без отражения и хочу получить его фактический тип, чтобы я мог создавать связанные объекты ( например, «Result<Animal>»). Я также пишу код фреймворка, поэтому не могу просто явно привести к типу. Есть ли разумный способ сделать это?

Я имею дело с сериализацией и хочу иметь возможность использовать полученный тип при создании связанных объектов: например, если я десериализую в "* 1009" * ", Я хочу создать экземпляр контейнера, например," Result<Animal> ". Для этого мне нужен тип (T), а не экземпляр типа (Type).

Я обнаружил, что могу заранее создать список статически типизированных вспомогательных классов (Helper<Animal>, Helper<Person>, ...), найдите нужный через «deserializedAnimal.runtimeType», затем вызовите, скажем, «buildResult(deserializedAnimal)». Это, будучи специально созданным для Animal s, знает, что имеет дело с Animal и может явно создать Result<Animal>.

. Я также нашел способ сделать это в общем, добавив метод к помощник с общим аргументом закрытия c. Помощник связывает параметр типа замыкания с типом stati c перед его вызовом. В результате замыкание получает экземпляр, который имеет соответствующий тип среды выполнения и тип c, плюс его параметр типа правильно привязан и может использоваться для создания экземпляров других типов (например, Result<T> с T, привязанным к Animal).

Все это кажется немного запутанным, но я убежден, что мне нужно что-то подобное, чтобы восстановить параметр типа после сериализации (опять же, чтобы я мог передать результат обобщенному c и поверьте, что параметр типа привязан к фактическому типу stati c, а не, скажем, dynamic).

Кажется ли что-нибудь из этого шатким? Не хватает чего-нибудь попроще?

Пример кода:

class Identifiable<T> {
  Id<T> id;
}

class Id<T> {}

class Person extends Identifiable<Person> {}

class Animal extends Identifiable<Animal> {}

class Resolver<T extends Identifiable> {
  void resolve(dynamic arg, void Function<V extends Identifiable>(dynamic) func) {
    func<T>(arg);
  }
}

final dynamic resolvers = {
  Id<Person>().runtimeType: Resolver<Person>(),
  Id<Animal>().runtimeType: Resolver<Animal>()
};

void reveal<T extends Identifiable>(Id<T> id) {
  print("Static: ${Id<T>().runtimeType}");
  print("Dynamic: ${id.runtimeType}\n");
}

void resolve(dynamic arg, void Function<V extends Identifiable>(dynamic) func) {
  resolvers[arg.runtimeType].resolve(arg, func);
}

main() {
  dynamic lst = [];
  
  lst.add(Id<Person>());
  lst.add(Id<Animal>());
  
  /*
    Static: Id<Identifiable<dynamic>>
    Dynamic: Id<Person>
  */
  reveal(lst[0]);

  /*
    Static: Id<Person>
    Dynamic: Id<Person>
  */
  resolve(lst[0], <V extends Identifiable>(arg){
    reveal<V>(arg);
  });
}

1 Ответ

1 голос
/ 02 августа 2020

То, что вы делаете, - это самый простой способ go из Type объекта ввести переменную, привязанную к этому типу (или любую другую функцию, которая зависит от точного типа, например, фабричная функция).

Невозможно go напрямую от Type объекта к используемому типу без отражения, потому что это - это отражение.

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