[seasar-dotnet:446] Nullable型にIdentityを指定するとキャストエラー

羽田 t_hada @ atlascorp.co.jp
2007年 2月 16日 (金) 11:17:38 JST


はじめまして、お世話になります。
羽田と申します。

現在、S2Dao.NETを利用させていただいています。
S2Dao.NET利用時、Identityを.NET 2.0のNullable<long>やNullable<int>に
マップしようとしたところ、下記のようなエラーが発生してしまいました。

> System.InvalidCastException : 'System.Decimal' から
> 'System.Nullable`1[[System.Int32, mscorlib, Version=2.0.0.0,
Culture=neutral, PublicKeyToken=b77a5c561934e089]]'
> への無効なキャストです。
>
> 場所 System.Convert.DefaultToType(IConvertible value, Type targetType,
IFormatProvider provider)
> 場所 System.Decimal.System.IConvertible.ToType(Type type,
IFormatProvider provider)
> 場所 System.Convert.ChangeType(Object value, Type conversionType,
IFormatProvider provider)
> 場所 Seasar.Dao.Id.AbstractIdentifierGenerator.SetIdentifier(Object
bean, Object value)
> 場所 Seasar.Dao.Id.IdentityIdentifierGenerator.SetIdentifier(Object
bean, IDataSource ds)
> 場所 Seasar.Dao.Impl.InsertAutoHandler.PostUpdateBean(Object bean)
> 場所 Seasar.Dao.Impl.AbstractAutoHandler.Execute(IDbConnection
connection, Object bean)
> 場所 Seasar.Dao.Impl.AbstractAutoHandler.Execute(Object[] args)
> 場所 Seasar.Dao.Impl.AbstractAutoStaticCommand.Execute(Object[] args)
> 場所 Seasar.Dao.Interceptors.S2DaoInterceptor.Invoke(IMethodInvocation
invocation)
> 場所 Seasar.Framework.Aop.Proxy.AopProxy.Invoke(IMessage msg)
> 場所
System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData&
msgData, Int32 type)

調査してみましたところ、おそらくは下記のメソッドが原因なのではないかと考
えます。

> Seasar.Daoプロジェクト
> Seasar.Dao.Id/AbstractIdentifierGenerator.cs
>
> protected void SetIdentifier(object bean, object value)
> {
> if(propertyName == null) throw new EmptyRuntimeException("propertyName");
> PropertyInfo propertyInfo = bean.GetType().GetProperty(propertyName);
>
> if (propertyInfo.PropertyType == typeof(Nullables.NullableDecimal))
> {
> propertyInfo.SetValue(bean,
Nullables.NullableDecimal.Parse(value.ToString()), null);
> }
> #if !NET_1_1
> else if (propertyInfo.PropertyType == typeof(Decimal?))
> {
> propertyInfo.SetValue(bean, new Decimal?((Decimal)value), null);
> }
> #endif
> else {
> propertyInfo.SetValue(bean, Convert.ChangeType(value,
propertyInfo.PropertyType), null);
> }
> }

PropertyTypeがNullable<T>型のケースをNullable<Decimal>以外ハンドルしてい
ないので、
Convert.ChangeTypeにNullable型が直接入力されてしまいエラーになるのでは
ないかと思います。
問題の的がズレていたらすみません。

Identityはlongやintでとることも多いため、Nullable<long>やNullable<int>にも
対応できると助かるので、問題を解決できないでしょうか?

参考までに、 .NET 1.1で除外されるコードの部分を下記のように変更すると、
Nullable<int>やNullable<long>でも
マップできるようです。

> #if !NET_1_1
> // PropertyTypeがNullable<T>の時
> else if (this.IsNullableType(propertyInfo.PropertyType))
> {
> // T型へConvert.ChangeTypeしてSetValueする。
> Type nullableTType = this.GetNullableTType(propertyInfo.PropertyType);
> propertyInfo.SetValue(
> bean,
> Convert.ChangeType(value, nullableTType), null);
> }
> #endif
>
> #if !NET_1_1
> // GenericTypeであるとき、GenericTypeの定義がNullable<>であればtrue
> private bool IsNullableType(Type type)
> {
> return type.IsGenericType &&
type.GetGenericTypeDefinition().Equals(typeof(Nullable<>));
> }
>
> // TypeがNullable<T>の時、Tを取得。
> private Type GetNullableTType(Type type)
> {
> return type.GetGenericArguments()[0];
> }
> #endif

以上よろしくお願いします。

/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
株式会社アトラス
羽田 拓央

〒510-0815
三重県四日市市野田2丁目1番10号
TEL(059)334-0609
FAX(059)334-1620
mail: t_hada @ atlascorp.co.jp
/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
<cid:part1.05090402.03080505 @ atlascorp.co.jp>


seasar-dotnet メーリングリストの案内