TypeIntializerException in RELEASE only

TypeIntializerException in RELEASE only

Old forum URL: forums.lhotka.net/forums/t/11193.aspx


JonM posted on Friday, February 24, 2012

I've got a Silverlight MVVM app. (CSLA.net 4.1)    When compiling debug everything works fine.  When I compile in release mode (like our build server) I have severe problems.  All of my list item screens have entries but the databound values are all blank.  When I attach a debugger I get TypeIntializer exceptions for every item and every property.  I'm posting the stack trace and source for the properties.  I would appreciate any help here.  I've tried different overloads of the GetProperty and SetProperty calls with no luck. 

Stacktrace for an error when binding to property

A first chance exception of type 'System.InvalidOperationException' occurred in Csla
A first chance exception of type 'System.TypeInitializationException' occurred in Agilis.CSLA
A first chance exception of type 'System.Reflection.TargetInvocationException' occurred in mscorlib.dll
System.Windows.Data Error: Cannot get 'FullName' value (type 'System.String') from 'Agilis.CSLA.OperatorListItem' (type 'Agilis.CSLA.OperatorListItem'). . System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.TypeInitializationException: The type initializer for 'Agilis.CSLA.OperatorListItem' threw an exception. ---> System.InvalidOperationException: Cannot register property OperatorID after containing type (OperatorListItem) has been instantiated
   at Csla.Core.FieldManager.PropertyInfoManager.RegisterProperty[T](Type objectType, PropertyInfo`1 info)
   at Csla.BusinessBase`1.RegisterProperty[P](PropertyInfo`1 info)
   at Csla.BusinessBase`1.RegisterProperty[P](Expression`1 propertyLambdaExpression, String friendlyName)
   at Agilis.CSLA.OperatorListItem..cctor()
   --- End of inner exception stack trace ---
   at Agilis.CSLA.OperatorListItem.get_FullName()
   --- End of inner exception stack trace ---
   at System.RuntimeMethodHandle.InvokeMethod(Object target, Object[] arguments, Signature sig, Boolean constructor)
   at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture, Boolean skipVisibilityChecks)
   at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
   at System.Reflection.RuntimePropertyInfo.GetValue(Object obj, BindingFlags invokeAttr, Binder binder, Object[] index, CultureInfo culture)
   at System.Reflection.RuntimePropertyInfo.GetValue(Object obj, Object[] index)
   at System.Windows.CLRPropertyListener.get_Value()
   at System.Windows.PropertyAccessPathStep.ConnectToPropertyInSource(Boolean isSourceCollectionViewCurrentItem).

Code for OperatorListItem Properties region

    [Serializable()]
    public class OperatorListItem : BusinessBase<OperatorListItem>
    {
        #region Business Methods
 
        private static PropertyInfo<int> OperatorIDProperty = RegisterProperty<int>(o => o.OperatorID, "OperatorID");
        public int OperatorID
        {
            get { return GetProperty<int>(OperatorIDProperty); }
            set { SetProperty<int>(OperatorIDProperty, value); }
        }
 
        private static PropertyInfo<string> LoginProperty = RegisterProperty<string>(o => o.Login, "Login");
        public string Login
        {
            get { return GetProperty<string>(LoginProperty); }
            set { SetProperty<string>(LoginProperty, value); }
        }
 
        private static PropertyInfo<string> FullNameProperty = RegisterProperty<string>(o => o.FullName, "FullName");
        public string FullName
        {
            get { return GetProperty<string>(FullNameProperty); }
            set { SetProperty<string>(FullNameProperty, value); }
        }
 
        private static PropertyInfo<bool> IsEnabledProperty = RegisterProperty<bool>(o => o.IsEnabled, "IsEnabled");
        public bool IsEnabled
        {
            get { return GetProperty<bool>(IsEnabledProperty); }
            set { SetProperty<bool>(IsEnabledProperty, value); }
        }
 
        private static PropertyInfo<string> RolesProperty = RegisterProperty<string>(o => o.Roles, "Roles");
        public string Roles
        {
            get { return GetProperty<string>(RolesProperty); }
            set { SetProperty<string>(RolesProperty, value); }
        }

 

RockfordLhotka replied on Friday, February 24, 2012

You must define the RegisterProperty fields as public.

This is because the compiler will optimize away other techniques to force initialization of static fields (like the old _forceInit trick I used to recommend). The release mode compiler starting with SL4 (or SL3?) added this optimization.

To address that issue, CSLA includes code that does force initialization of static fields, but the fields must be public. Hence, it is a requirement that the RegisterProperty fields be public when building apps for Silverlight, Windows Phone, or WinRT.

Basically, you should just always make them public.

JonM replied on Friday, February 24, 2012

Thanks Rocky!  That worked.  Now, the only reason I can imagine that it was marked private is because I built up my objects using different csla samples.  (probably old samples now).  I've bought and watched the MVVM video series and it is really good!  Should I have the newer eBook series for CSLA 4?  Do you think it is worth it for Silverlight+MVVM apps?

Thanks again!

RockfordLhotka replied on Friday, February 24, 2012

The Using CSLA 4 books are the most current and comprehensive documentation for the framework. They go deeper than the CSLA 4 MVVM video series - it is possible to put more content into book than a video.

Copyright (c) Marimer LLC