We have a custom LocalizedString type used in our domain model. We want to decorate the properties with validation attributes like MaxLength
. For this, we added implicit operators to enable casts required by this attribute.
Strangely, the operator seems to never get called and an InvalidCastException get's thrown in the attributes IsValid
method. Performing this cast in our own project works.
Is there a special cast behavior compiler magix going on in this system clr ngen'ed attribute or something?
// Custom type
public class LocalizedString
{
public string Value
{
get { return string.Empty; }
}
public static implicit operator Array(LocalizedString localizedString)
{
if (localizedString.Value == null)
{
return new char[0];
}
return localizedString.Value.ToCharArray();
}
}
// Type: System.ComponentModel.DataAnnotations.MaxLengthAttribute
// Assembly: System.ComponentModel.DataAnnotations, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35
// Assembly location: C:\Windows\Microsoft.NET\Framework\v4.0.30319\System.ComponentModel.DataAnnotations.dll
public override bool IsValid(object value)
{
this.EnsureLegalLengths();
if (value == null)
{
return true;
}
else
{
string str = value as string;
int num = str == null ? ((Array) value).Length : str.Length;
if (-1 != this.Length)
return num <= this.Length;
else
return true;
}
}
[TestMethod]
public void CanCallIsValidWithLocalizedString()
{
// Arrange
var attribute = new MaxLengthAttribute(20);
var localized = new LocalizedString { Value = "123456789012345678901" };
// Act
var valid = attribute.IsValid(localized);
// Assert
Assert.IsFalse(valid);
}
Thanks for your help.
Edit
Das Objekt des Typs "Nexplore.ReSearch.Base.Core.Domain.Model.LocalizedString" kann nicht in Typ "System.Array" umgewandelt werden.
bei System.ComponentModel.DataAnnotations.MaxLengthAttribute.IsValid(Object value)
bei Nexplore.ReSearch.Base.Tests.Unit.Infrastructure.CodeFirst.MaxLengthLocalizedAttributeTests.CanCallIsValidWithLocalizedString() in d:\Nexplore\SourceForge\Nexplore.ReSearch.Base\Source\Nexplore.ReSearch.Base.Tests.Unit\Infrastructure.CodeFirst\MaxLengthLocalizedAttributeTests.cs:Zeile 40.
Operators of any kind only apply if the type of object is known at compile time. They are not applied "on the fly" to object
.
You could try using dynamic
which does do that.
Examples:
using System;
class Foo
{
public static implicit operator Array(Foo foo)
{
return new int[0]; // doesn't matter
}
static void Main()
{
Foo foo = new Foo();
Array x = (Array)foo; // implicit operator called via compiler
dynamic dyn = foo;
Array y = (Array)dyn; // implicit operator called via dynmic
object obj = foo;
Array z = (Array)obj; // implicit operator NOT called
// - this is a type-check (BOOM!)
}
}