using F# with CSLA and TypeInitializationException

using F# with CSLA and TypeInitializationException

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


emathias posted on Thursday, April 11, 2013

After earlier failure, I decided to revisit the use of CSLA with F#.  I keep running into the same issue in that the static RegisterProperty throws a typeinitializationexception.  I wrote a test combo C# / F# solution with 2 libraries and a console app displayed below.  I wrote a csla C# object, a duplicate (I think) F# object and a console app that instantiates both of them.  The most interesting aspect of this is if I remove the static modifiers from the propertyinfo and registerproperty calls in the F# object, it works, but only for 1 object. A subsequent call gives the expected error that the property has already been registered.

I ran both DLLs through a decompiler and C# creates the expected call to RegisterProperty in the static constructor.  However the F# does not create the same static constructor call.   

Does anyone know why this is happening in the F# class?  Also, has anyone had any luck building CSLA apps within F#.  If so, then I'm likely guilty of operator error and could use some guidance.


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace RunCSharpVsFSharp
{
    class Program
    {
        static void Main(string[] args)
        {
            // Call to CSharpObjects below works correctly
            try
            {
                var a = CSharpObjects.EditableRoot.GetEditableRoot();
                a.Name = "David Gilmour";
            }
            catch(System.Exception ex)
            {
                throw ex;
            }

            // below code results in a typeinitializationexception with inner exception message
            // of "Attempt by method '<StartupCode$FSharpObjects>.$EditableRoot..cctor()' to access method
            // 'Csla.BusinessBase`1<FSharpObjects.EditableRoot>.RegisterProperty<System.String>(Csla.PropertyInfo`1<System.String>)'
            // failed."
            try
            {
                var a = FSharpObjects.EditableRoot.GetEditableRoot;
                a.Name = "Roger Waters";
            }
            catch (System.Exception ex)
            {
                throw ex;
            }

        }
    }
}

======================================================================

namespace FSharpObjects

    open System.Collections.Generic
    open System.Linq
    open System.Text
    open System.Threading.Tasks

    open Csla
    open Csla.Serialization

        type public EditableRoot() =
            inherit BusinessBase<EditableRoot>()

            static let propinfo = new PropertyInfo<string>("Name")
            static let NameProperty = EditableRoot.RegisterProperty<string>(typeof<EditableRoot>,propinfo)
        
            member x.Name
                with get() = x.GetProperty(NameProperty)
                and set(value) = x.SetProperty(NameProperty, value);

            static member GetEditableRoot = new EditableRoot()

======================================================================

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using Csla;

namespace CSharpObjects
{
    [Serializable]
    public class EditableRoot : BusinessBase<EditableRoot>
    {
        private EditableRoot()
        {
        }

        private static PropertyInfo<string> propinfo = new PropertyInfo<string>("Name");
        public static readonly PropertyInfo<string> NameProperty = RegisterProperty<string>(propinfo);
        public string Name
        {
            get { return GetProperty(NameProperty); }
            set { SetProperty(NameProperty, value); }
        }

        public static EditableRoot GetEditableRoot()
        {
            return new EditableRoot();
        }
    }
}

RockfordLhotka replied on Monday, April 15, 2013

I haven't done anything with F#, so I can't really help.

CSLA does rely heavily on the standard static type initialization behaviors provided by the C# and VB compilers. If F# provides some alternate static type initialization behavior then you'll need to figure out some way to trigger the required behaviors in your own code.

Copyright (c) Marimer LLC