You are viewing a plain text version of this content. The canonical link for it is here.
Posted to user-cs@ibatis.apache.org by "Wyatt, Mike" <Mi...@quadsystems.com> on 2008/11/10 22:26:24 UTC

Lazy-Loaded null reference properties

Class State contains a reference to class City.  That reference is
configured in the ResultMap to be lazy-loaded.  Class City has a simple
string property called Name.  

    public class State
    {
        private City _capital;
        public City Capital { get { return _capital; } set { _capital =
value; } }
    }

    public class City
    {
        private string _name;
        public string Name { get { return _name; } set { _name= value; }
}
    }

    State state = _mapper.QueryForObject<State> ( "GetState", "WI" );
    Console.Write( state.Capital.Name );

Accessing state.Capital.Name throws a "TargetException: Non-static
method requires a target" exception:  

    [TargetException: Non-static method requires a target.]
       System.Reflection.RuntimeMethodInfo.CheckConsistency(Object
target) +7515801
       System.Reflection.RuntimeMethodInfo.Invoke(Object obj,
BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo
culture, Boolean     skipVisibilityChecks) +105
       System.Reflection.RuntimeMethodInfo.Invoke(Object obj,
BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo
culture) +29
 
IBatisNet.DataMapper.Proxy.LazyLoadInterceptor.Intercept(IInvocation
invocation, Object[] arguments) +391
 
CProxyTypeState_System_Runtime_SerializationISerializable1.get_Name()
+190
    [MethodInvocationException: Invocation of method 'Name' in
CProxyTypeState_System_Runtime_SerializationISerializable1 threw an
exception]

I'm using iBATIS in a web app that uses NVelocity to render web pages.
NVelocity will ignore NullReferenceExceptions, but not TargetExceptions,
when rendering dynamic tags (i.e. $state.City.Name).

My proposed solution is simple.  In
IBatisNet.DataMapper.Proxy.LazyLoadInterceptor, the invocation of the
returnValue on line 133 should be modified to throw a
NullReferenceException if _lazyLoadedItem is null.

*Before*
	object returnValue = invocation.Method.Invoke( _lazyLoadedItem,
arguments);		

*After*
	if( _lazyLoadedItem == null )
	{
		throw new NullReferenceException();
	}

	object returnValue = invocation.Method.Invoke( _lazyLoadedItem,
arguments);		

Thoughts on this solution or possible workarounds?


RE: Lazy-Loaded null reference properties

Posted by "Wyatt, Mike" <Mi...@quadsystems.com>.
Oops, forgot two points:
 
1)  The lazy-loaded City object in the example is null.  (i.e.
state.Capital.Name would throw a NullReferenceException if lazy-loading
weren't enabled).
2)  The public properties in the State and City classes should both be
virtual.

________________________________

From: Wyatt, Mike [mailto:Michael.Wyatt@quadsystems.com] 
Sent: Monday, November 10, 2008 3:26 PM
To: user-cs@ibatis.apache.org
Subject: Lazy-Loaded null reference properties



Class State contains a reference to class City.  That reference is
configured in the ResultMap to be lazy-loaded.  Class City has a simple
string property called Name.  

    public class State 
    { 
        private City _capital; 
        public City Capital { get { return _capital; } set { _capital =
value; } }
    } 

    public class City 
    { 
        private string _name; 
        public string Name { get { return _name; } set { _name= value; }
}
    } 

    State state = _mapper.QueryForObject<State> ( "GetState", "WI" ); 
    Console.Write( state.Capital.Name ); 

Accessing state.Capital.Name throws a "TargetException: Non-static
method requires a target" exception:  

    [TargetException: Non-static method requires a target.] 
       System.Reflection.RuntimeMethodInfo.CheckConsistency(Object
target) +7515801 
       System.Reflection.RuntimeMethodInfo.Invoke(Object obj,
BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo
culture, Boolean     skipVisibilityChecks) +105

       System.Reflection.RuntimeMethodInfo.Invoke(Object obj,
BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo
culture) +29

 
IBatisNet.DataMapper.Proxy.LazyLoadInterceptor.Intercept(IInvocation
invocation, Object[] arguments) +391 
 
CProxyTypeState_System_Runtime_SerializationISerializable1.get_Name()
+190 
    [MethodInvocationException: Invocation of method 'Name' in
CProxyTypeState_System_Runtime_SerializationISerializable1 threw an
exception]

I'm using iBATIS in a web app that uses NVelocity to render web pages.
NVelocity will ignore NullReferenceExceptions, but not TargetExceptions,
when rendering dynamic tags (i.e. $state.City.Name).

My proposed solution is simple.  In
IBatisNet.DataMapper.Proxy.LazyLoadInterceptor, the invocation of the
returnValue on line 133 should be modified to throw a
NullReferenceException if _lazyLoadedItem is null.

*Before* 
        object returnValue = invocation.Method.Invoke( _lazyLoadedItem,
arguments);             

*After* 
        if( _lazyLoadedItem == null ) 
        { 
                throw new NullReferenceException(); 
        } 

        object returnValue = invocation.Method.Invoke( _lazyLoadedItem,
arguments);             

Thoughts on this solution or possible workarounds?