モデル内の他のいくつかのプロパティの値に応じて、プロパティに値が含まれていることを検証する If-IsRequired カスタム属性を作成しました。この属性をできるだけ多くの状況に適用したいので、開発者がこの属性を利用して、一致するパラメーターを無数に指定できるオプションを許可したいと考えています。最後に、すべてのパラメーターが正しく一致するように強制できるようにしたいと考えています。
ここまで書いてきました。私は現在、文字列の配列を使用していますが、動作できなかったある種のコレクションを使用できれば幸いです。さらに、現在の属性定義をサポートし、比較演算子を含む新しいオーバーロードを作成する必要があります。これにより、すべての比較が等号で行われると仮定する元の定義に加えて、より小さい、より大きい、および等しくない比較を行うことができます。
/// <summary>
/// A custom attribute that checks the value of other properties passed to it in order to
/// determine if the property this attribute is bound to should be required.
/// </summary>
[AttributeUsage(AttributeTargets.Property, AllowMultiple = true, Inherited = true)]
public class IsPropertyRequiredAttribute : ValidationAttribute
{
private const string DefaultErrorMessage = "{0} is required.";
public string[] _selectionContextNames { get; private set; }
public string[] _expectedValues { get; private set; }
/// <summary>
/// Creates a new instance of the IsPropertyRequriedAttribute.
/// </summary>
/// <param name="SelectionContextNames">The name of the other property in the view model to check the value of.</param>
/// <param name="ExpectedValues">The expected value of the other property in the view model in order to determine if the current property the attribute is bound to should be required.</param>
public IsPropertyRequiredAttribute(string[] SelectionContextNames, string ExpectedValues)
: base(DefaultErrorMessage)
{
_selectionContextNames = SelectionContextNames;
_expectedValues = ExpectedValues;
}
public override bool IsValid(object value)
{
if (_selectionContextNames == null || _expectedValues == null)
{
if (_selectionContextNames != null || _expectedValues != null)
{
string paramName;
if (_selectionContextNames == null)
{
paramName = "ExpectedValues";
}
else
{
paramName = "SelectionContextNames";
}
throw new ArgumentException("Key/Value pairs need to match for IsPropertyRequired.", paramName);
}
}
else if (_selectionContextNames.Length != _expectedValues.Length)
{
string paramName;
if (_selectionContextNames.Length < _expectedValues.Length)
{
paramName = "ExpectedValues";
}
else
{
paramName = "SelectionContextNames";
}
throw new ArgumentException("Parameter element counts need to match for IsPropertyRequired.", paramName);
}
bool paramsValid = true;
if (_selectionContextName!= null)
{
for (int i = 0; i < _selectionContextName.Length; i++)
{
string paramValue = HttpContext.Current.Request[_selectionContextName[i]];
if (_expectedValue[i] != paramValue)
{
paramsValid = false;
}
}
if (paramsValid == true)
{
return (value != null);
}
else
{
return true;
}
}
else
{
return true;
}
}
public override string FormatErrorMessage(string name)
{
return String.Format(DefaultErrorMessage, name);
}
}
属性を使用してプロパティを装飾するかどうかは、属性の定義方法によって異なりますが、これは私が現在実装しているものです (これもおそらく改善される可能性があります)。
[IsPropertyRequired(new string[] {"prop1", "prop2", "prop3", "prop4"}, new string[] {"1", "2", "3", "4"})]
public string SomeText { get; set; }
また、次の装飾が行われないように、できる限り防止したいと考えています。
[IsPropertyRequired(new string[] {"prop1", "prop2", "prop3", "prop4", "prop5withoutvalue"}, new string[] {"1", "2", "3", "4"})]
public string SomeOtherText { get; set; }
また、比較演算子をパラメーターとして含む新しいオーバーロードを使用すると、次のようになります。
[IsPropertyRequired(new string[] {"prop1", "prop2", "prop3", "prop4"}, new string[] {"==", ">", "!=", "<="}, new string[] {"1", "2", "3", "4"})]
public string SomeComparisonText { get; set; }