#dart #dart-mirrors
#dart #dart-зеркала
Вопрос:
Я пытаюсь воссоздать функциональность djangos QueryDict и создать объект, которому можно присвоить карту, и он будет частной переменной в объекте, а геттеры / сеттеры используются для динамического извлечения из карты. Мне удалось воссоздать метод get (), но я теряюсь при динамическом получении значения. Вот что у меня есть до сих пор:
class QueryMap {
Map _data;
QueryMap(Map this._data);
dynamic get(String key, [var defaultValue]) {
if(this._data.containsKey(key)) {
return this._data[key];
} else if(defaultValue) {
return defaultValue;
} else {
return null;
}
}
}
Вот страница djangos о том, как это работает:
https://docs.djangoproject.com/en/dev/ref/request-response/#django.http .QueryDict.getitem
Ответ №1:
Вы можете переопределить noSuchMethod
(эмулирующие функции)
@proxy
class QueryMap {
Map _data = new Map();
QueryMap();
noSuchMethod(Invocation invocation) {
if (invocation.isGetter) {
var ret = _data[invocation.memberName.toString()];
if (ret != null) {
return ret;
} else {
super.noSuchMethod(invocation);
}
}
if (invocation.isSetter) {
_data[invocation.memberName.toString().replaceAll('=', '')] =
invocation.positionalArguments.first;
} else {
super.noSuchMethod(invocation);
}
}
}
void main() {
QueryMap qaueryMap = new QueryMap();
qaueryMap.greet = "Hello Dart!";
print(qaueryMap.greet); //Hello Dart!
}
Как отметил @PixelElephant с внешней картой, вы должны использовать реальные имена методов в качестве ключей карты:
import 'dart:mirrors';
@proxy
class QueryMap {
Map _data;
QueryMap(this._data);
noSuchMethod(Invocation invocation) {
if (invocation.isGetter) {
var ret = _data[MirrorSystem.getName(invocation.memberName)];
if (ret != null) {
return ret;
} else {
super.noSuchMethod(invocation);
}
}
if (invocation.isSetter) {
_data[MirrorSystem.getName(invocation.memberName).replaceAll('=', '')] =
invocation.positionalArguments.first;
} else {
super.noSuchMethod(invocation);
}
}
}
void main() {
Map myMap = new Map();
myMap["color"] = "red";
QueryMap qaueryMap = new QueryMap(myMap);
qaueryMap.greet = "Hello Dart!";
print(qaueryMap.greet); //Hello Dart!
print(qaueryMap.color); //red
}
Чтобы избежать использования зеркал, вы можете использовать сопоставление с образцом при сериализации строки символа или преобразовании внешних ключей карты:
@proxy
class QueryMap {
Map _data;
QueryMap(Map data) {
_data = new Map();
data.forEach((k, v) => _data[new Symbol(k).toString()] = v);
}
noSuchMethod(Invocation invocation) {
if (invocation.isGetter) {
var ret = _data[invocation.memberName.toString()];
if (ret != null) {
return ret;
} else {
super.noSuchMethod(invocation);
}
}
if (invocation.isSetter) {
_data[invocation.memberName.toString().replaceAll('=', '')] =
invocation.positionalArguments.first;
} else {
super.noSuchMethod(invocation);
}
}
}
void main() {
Map myMap = new Map();
myMap["color"] = "red";
QueryMap qaueryMap = new QueryMap(myMap);
qaueryMap.greet = "Hello Dart!";
print(qaueryMap.greet); //Hello Dart!
print(qaueryMap.color); //red
}
Комментарии:
1. Обратите внимание, что
memberName
это aSymbol
, и вы должны вызватьMirrorSystem.getName
его, чтобы получить строку, которую вы можете использовать в качестве ключа (вместо toString ).2. @PixelElephant Я старался избегать использования зеркал в любой форме или форме, потому что они могут повлиять на производительность.
3. Да, но они нужны здесь. Ваш код работает только потому, что вы оба устанавливаете и получаете, используя noSuchMethod. Если бы вы использовали уже созданную карту, например
Map map = {'greet': 'Hello Dart'};
, код потерпел бы неудачу, поскольку он пытается получитьSymbol('greet')
, а не простоgreet
.4. @PixelElephant Спасибо, это верная точка зрения. Я забыл, что он использует внешнюю карту.
5. Это довольно гениально! Итак, я предполагаю, что последний метод будет работать и на flutter, где зеркала не разрешены? Также кто-нибудь имеет представление о снижении производительности при использовании этого? Это действительно помогает сократить много хлопот в нашей кодовой базе, поэтому у меня возникает соблазн использовать его