Техника, описанная в этой статье Яна Робертсона , работает для меня.
Короче, быстрый и грязный пример:
public abstract class AbstractDAO
{
/**
* Method returns class implementing EntityInterface which was used in class
* extending AbstractDAO
*
* @return Class
*/
public Class returnedClass()
{
return (Class) getTypeArguments(AbstractDAO.class, getClass()).get(0);
}
/**
* Get the underlying class for a type, or null if the type is a variable
* type.
*
* @param type the type
* @return the underlying class
*/
public static Class> getClass(Type type)
{
if (type instanceof Class) {
return (Class) type;
} else if (type instanceof ParameterizedType) {
return getClass(((ParameterizedType) type).getRawType());
} else if (type instanceof GenericArrayType) {
Type componentType = ((GenericArrayType) type).getGenericComponentType();
Class> componentClass = getClass(componentType);
if (componentClass != null) {
return Array.newInstance(componentClass, 0).getClass();
} else {
return null;
}
} else {
return null;
}
}
/**
* Get the actual type arguments a child class has used to extend a generic
* base class.
*
* @param baseClass the base class
* @param childClass the child class
* @return a list of the raw classes for the actual type arguments.
*/
public static List> getTypeArguments(
Class baseClass, Class extends T> childClass)
{
Map resolvedTypes = new HashMap();
Type type = childClass;
// start walking up the inheritance hierarchy until we hit baseClass
while (!getClass(type).equals(baseClass)) {
if (type instanceof Class) {
// there is no useful information for us in raw types, so just keep going.
type = ((Class) type).getGenericSuperclass();
} else {
ParameterizedType parameterizedType = (ParameterizedType) type;
Class> rawType = (Class) parameterizedType.getRawType();
Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
TypeVariable>[] typeParameters = rawType.getTypeParameters();
for (int i = 0; i < actualTypeArguments.length; i++) {
resolvedTypes.put(typeParameters[i], actualTypeArguments[i]);
}
if (!rawType.equals(baseClass)) {
type = rawType.getGenericSuperclass();
}
}
}
// finally, for each actual type argument provided to baseClass, determine (if possible)
// the raw class for that type argument.
Type[] actualTypeArguments;
if (type instanceof Class) {
actualTypeArguments = ((Class) type).getTypeParameters();
} else {
actualTypeArguments = ((ParameterizedType) type).getActualTypeArguments();
}
List> typeArgumentsAsClasses = new ArrayList>();
// resolve types by chasing down type variables.
for (Type baseType : actualTypeArguments) {
while (resolvedTypes.containsKey(baseType)) {
baseType = resolvedTypes.get(baseType);
}
typeArgumentsAsClasses.add(getClass(baseType));
}
return typeArgumentsAsClasses;
}
}
FWIW при создании поля Password ControlToValidate и полем Confirm Password ControlToCompare, затем это будет работать, потому что поле пароля будет иметь что-то в нем и следовательно выполнит проверку.
, Конечно, это могло позволить им отправлять форму с пустым полем Password, и заполненной - в поле Confirm, так помещая необходимый блок проверки допустимости на обоих является, вероятно, лучшая идея.
Также необходимо использовать RequiredFieldValidator. Много средств управления проверкой передаст, если поле будет пусто и потребность, которая будет соединена таким образом с RequiredFieldValidator.
Как насчет этого?
Два поля TextBox - txtEmail1 (для адреса электронной почты) и txtEmail2 (для подтверждения).
Присоединение RegularExpressionValidator к txtEmail1 - когда пробел, это не будет стрелять. при заполнении данные проверены.
Присоединение CompareValidator к txtEmail1, сравнивая его данные с txtEmail2. Затем присоедините CompareValidator к txtEmail2, сравнив его данные с txtEmail1.
, Это отвечает Вашему требованию, что поля могут быть оставлены незаполненные, но запускают логику проверки, если любое поле имеет данные.
- joe
CompareValidator, RegularExpressionValidator и средства управления проверкой RangeValidator работают над значениями непустой строки. Это полезно для ситуаций, где у нас есть необязательное поле, которое должно удовлетворить некоторое условие при вводе.
, Например, у нас есть форма с двумя полями: основная электронная почта, которая должна быть введена; и альтернативная электронная почта, которая не требуется, но при вводе это должно быть проверено. Для проверки этого, мы добавили бы RequiredFieldValidator и RegularExpressionValidator на основной адрес электронной почты и только RegularExpressionValidator к второму полю.
Это было бы хитро для проверки упомянутой формы, если бы RegularExpressionValidator был инициирован на пустом входе, и мы должны были бы изменить regex во втором для разрешения пустого значения, которое значительно более трудно сделать и поддержать и не так очевидное решение.
У меня была точно такая же проблема. Используйте CustomValidator вместо CompareValidator. (CustomValidator имеет полезный атрибут ValidateEmptyText, которого нет в CompareValidator, по крайней мере, в ASP.NET 2.0.)
Вам нужно будет запрограммировать соответствующую функцию ServerValidate, а также ClientValidationFunction. Сигнатура функции для функции javascript в основном такая же, как для функции ServerValidate: источник (объект), аргументы (ServerValidateEventArgs).
Самая сложная часть состоит в том, что вам нужно будет написать собственный код для доступа к текстовому полю «CompareTo», поскольку это не является частью CustomValidator. Мои поля были в FormView; вам может потребоваться изменить код в соответствии с вашими конкретными обстоятельствами. В приведенном ниже коде «fv» - это имя этого FormView.
Проверка на стороне клиента:
<script type="text/javascript">
<!--
function cvPasswordRpt_Validate(source, args)
{
args.IsValid = (args.Value ==
document.getElementsByName("fv$tbPassword").item(0).value);
}
//-->
</script>
Код ASPX:
<label>New Password:</label>
<asp:TextBox ID="tbPassword" runat="server" CssClass="stdTextField"
TextMode="Password" ValidationGroup="edit" />
<br />
<label>Repeat New Password:</label>
<asp:TextBox ID="tbPasswordRpt" runat="server" CssClass="stdTextField"
TextMode="Password" ValidationGroup="edit" />
<asp:CustomValidator ID="cvPasswordRpt" runat="server" Display="Dynamic"
EnableClientScript="true" ValidationGroup="edit"
ControlToValidate="tbPasswordRpt" ValidateEmptyText="true"
ErrorMessage="Your passwords do not match."
ClientValidationFunction="cvPasswordRpt_Validate"
OnServerValidate="cvPasswordRpt_ServerValidate" />
Проверка на стороне сервера (VB.NET):
Protected Sub cvPasswordRpt_ServerValidate(ByVal sender As Object,
ByVal e As ServerValidateEventArgs)
Dim _newPassword As String = DirectCast(fv.FindControl("tbPassword"),
TextBox).Text
e.IsValid = e.Value.Equals(_newPassword)
End Sub