Следующее предназначено для сбитого с толку, объясняющего, как работает привязка данных в Blazor:
Использование связывания со свойством PetitionInput (<input bind="@PetitionInput" />
) по существу эквивалентно следующему:
<input value="@PetitionInput"
onchange="@((UIChangeEventArgs __e) => PetitionInput= __e.Value)" />
[ 118] «Когда компонент визуализируется, значение элемента input берется из свойства PetitionInput. Когда пользователь вводит текстовое поле, вызывается событие onchange, а свойству PetitionInput устанавливается измененное значение. В принципе, bind связывает текущее значение выражения с атрибутом значения и обрабатывает изменения с помощью зарегистрированного обработчика. "
Проще говоря, когда вы используете атрибут bind (bind =" @ PetitionInput "), Blazor генерирует код, подобный this:
<input value="@PetitionInput"
onchange="@((UIChangeEventArgs __e) => PetitionInput= __e.Value)" />
Это так называемое двустороннее связывание данных. Теперь, если вы добавляете обработчик события для события onkeydown, код выполняет то, для чего он предназначен:
void PetitionHandleKeyDown(UIKeyboardEventArgs arg) {
PetitionInput += _petition[_petitionCharStep];
_petitionCharStep++;
}
Когда страница отображается впервые, текстовое поле по умолчанию пустое. Значение PetitionInput установлено в string.Empty:
public string PetitionInput { get; set; } = string.Empty;
Когда пользователь вводит текстовое поле, скажем, букву «N», он добавляется в свойство PetitionInput из-за двусторонней привязки (с использованием атрибута bind) и отображается в текстовом поле сразу после визуализации компонента размещения. Кроме того, код в методе PetitionHandleKeyDown добавляет букву «T» к свойству PetitionInput (при первом вводе), и, таким образом, строка «NT» отображается в текстовом поле сразу после визуализации компонента размещения. Конечно, способ предотвратить такое поведение (мы должны уважать желание спрашивающего) состоит в том, чтобы сделать то, что
мистер Магу сделал выше. Простой и элегантный, отражающий понимание привязки данных и работы Blazor.
Я сам настоящим предлагаю обходное решение для данной проблемы:
Ну, что я хотел сделать возможным, было что-то как этот:
@Contract({
@ExclusiveOr({
@IsType(IAtomicType.class),
@Or({
@IsType(IListType.class),
@IsType(ISetType.class)
})
})
})
Предложенное обходное решение:
Определите класс с конструктором без параметров (который назовет Ваш собственный процессор аннотации позже) следующим способом:
final class MyContract extends Contract{
// parameter-less ctor will be handeled by annotation processor
public MyContract(){
super(
new ExclusiveOr(
new IsType(IAtomicType.class),
new Or(
new IsType(IListType.class),
new IsType(ISetType.class)
)
)
);
}
}
использование:
@Contract(MyContract.class)
class MyClass{
// ...
}
Ошибка производится, потому что Вы не можете использовать интерфейсы в качестве значений аннотации (измените ее на Comparable
и Вы получите ту же ошибку). От JLS:
Это - ошибка времени компиляции, если тип возврата метода, объявленного в типе аннотации, является каким-либо типом кроме одного из следующего: одни из типов примитивов,
String
,Class
и любой вызовClass
, перечислимый тип, тип аннотации или массив одного из предыдущих типов. Это - также ошибка времени компиляции, если какой-либо метод, объявленный в типе аннотации, имеет подпись, которая эквивалентна переопределению тому из любогоpublic
илиprotected
метод объявляется в классеObject
или в интерфейсеannotation.Annotation
.
Я боюсь, что не знаю о хорошем обходном решении, но теперь по крайней мере, Вы знаете, почему Вы получаете ошибку.
Можно сделать:
Class<? extends Annotation>[] value();
Не уверенный, если это помогает, но...