System.NullReferenceException with F# and iOS on Xamarin - ios

I have a very strange error when executing some test code testing a different module that is hosted in a standalone project but within the same solution within Xamarin Studio.
The solution hosts 2 projects. A module-project and a test-project. The test-project references the module-project via a project-reference.
//module-project/FluidLayout.fs
namespace iosautolayout
open System
module Fluidity =
type Init<'a> = Init of 'a
type Right<'a> = Right of 'a
type Left<'a> = Left of 'a
type HorizontalBuilder() =
member x.Yield(()) = Init "Init"
[<CustomOperation("part")>]
member x.Part(Init v, a) = Left "Left"
let horizontal = new HorizontalBuilder()
let create () =
let test_h = horizontal {
part "test"
}
test_h
Then I have the test project with 2 files in it
//test-project/Tests.fs
namespace ioslibrarytests
open System
open NUnit.Framework;
open iosautolayout.Fluidity
open MonoTouch.UIKit
open MonoTouch.Foundation
#nowarn "0025"
[<TestFixture>]
type Tests() =
[<Test>]
member me.``Create Structure with DSL``() =
let z = create ()
()
And the AppDelegate to start everything
//test-project/AppDelegate.fs
namespace ioslibrarytests
open System
open MonoTouch.UIKit
open MonoTouch.Foundation
open MonoTouch.NUnit.UI
[<Register("AppDelegate")>]
type AppDelegate() =
inherit UIApplicationDelegate()
override val Window = null with get, set
override this.FinishedLaunching(app, options) =
this.Window <- new UIWindow(UIScreen.MainScreen.Bounds)
let runner = new TouchRunner(this.Window)
runner.Add (System.Reflection.Assembly.GetExecutingAssembly ());
this.Window.RootViewController <- new UINavigationController (runner.GetViewController ());
this.Window.MakeKeyAndVisible()
true
module Main =
[<EntryPoint>]
let main args =
UIApplication.Main(args, null, "AppDelegate")
0
This gives me the following error
2015-02-15 15:11:46.902 ioslibrarytests[1017:14804]
[FAIL] Create Structure with DSL : System.NullReferenceException :
Object reference not set to an instance of an object
2015-02-15 15:11:46.902 ioslibrarytests[1017:14804] at
iosautolayout.Fluidity.create () [0x00000] in
/Users/projekte/pawo-pic/ios-autolayout/FluidLayout.fs:17
2015-02-15 15:11:46.902 ioslibrarytests[1017:14804] at
ioslibrarytests.Tests.Create Structure with DSL () [0x00000] in
/Users/projekte/pawo-pic/ios-library-tests/Tests.fs:17
2015-02-15 15:11:46.902 ioslibrarytests[1017:14804] at
(wrapper managed-to-native) System.Reflection.MonoMethod:InternalInvoke
(System.Reflection.MonoMethod,object,object[],System.Exception&)
2015-02-15 15:11:46.902 ioslibrarytests[1017:14804] at
System.Reflection.MonoMethod.Invoke (System.Object obj, BindingFlags
invokeAttr, System.Reflection.Binder binder, System.Object[] parameters,
System.Globalization.CultureInfo culture) [0x00044] in
/Developer/MonoTouch/Source/mono/mcs/class/corlib/System.Reflection/MonoMethod.cs:230 201
I am completely lost to what happens here.
Your help is appreciated.

I found a solution - But now I am even more confused.
If I change horizontal to a function instead of a val all works fine
namespace iosautolayout
open System
module Fluidity =
type Init<'a> = Init of 'a
type Right<'a> = Right of 'a
type Left<'a> = Left of 'a
type HorizontalBuilder() =
member x.Yield(()) = Init "Init"
[<CustomOperation("part")>]
member x.Part(Init v, a) = Left "Left"
let horizontal () = new HorizontalBuilder()
let create () =
let test_h = horizontal() {
part "test"
}
test_h
In the interactive Window it doesnt matter if I use horizontal as value or as a function.
Can anybody shed some light on this behavior?

Related

Compilation error when trying to use topics with EasyNetQ in F#

I am trying to subscribe to a RabbitMq topic using the PubSub.Subscribe method in EasyNetq with F#. The function subscribeToAppQueueWithoutTopic compiles and works but the subscribeToAppQueueWithTopic function will not compile at all.
let subscribeToAppQueueWithTopic (callback : Subscription<AppEnvelope>) =
bus.PubSub.Subscribe<AppEnvelope>(String.Empty, callback.OnMessageReceived,
(fun (x:ISubscriptionConfiguration) -> x.WithTopic("app.queue")), cts.Token)
Error FS0041 No overloads match for method 'Subscribe'.
Known types of arguments: string * (AppEnvelope -> unit) * (ISubscriptionConfiguration -> ISubscriptionConfiguration) * CancellationToken
Available overloads:
- (extension) IPubSub.Subscribe<'T>(subscriptionId: string, onMessage: Action<'T>, configure: Action<ISubscriptionConfiguration>, ?cancellationToken: CancellationToken) : ISubscriptionResult // Argument 'configure' doesn't match
- (extension) IPubSub.Subscribe<'T>(subscriptionId: string, onMessage: Func<'T,CancellationToken,Tasks.Task>, configure: Action<ISubscriptionConfiguration>, ?cancellationToken: CancellationToken) : ISubscriptionResult // Argument 'onMessage' doesn't match
I found a c# example of subscribing with a topic here EasyNetQ subscription tests which looks like this
bus.PubSub.SubscribeAsync<Message>(
Guid.NewGuid().ToString(),
firstTopicMessagesSink.Receive,
x => x.WithTopic("first"),
cts.Token
and thought I could use fun (x:ISubscriptionConfiguration) -> x.WithTopic("app.queue") as equivalent in F#. Alas this will not compile.
Here is an example app showing the problem
open System
open EasyNetQ
open System.Threading
type Subscription<'T> = { OnMessageReceived: 'T -> unit }
[<Queue("appqueue", ExchangeName = "demopappexchange")>]
type AppEnvelope = { Message : obj }
[<EntryPoint>]
let main argv =
let bus = RabbitHutch.CreateBus("host=localhost")
let cts = new CancellationTokenSource(TimeSpan.FromSeconds(5));
let printMessage message =
printfn "%s" message
let subscription = {
OnMessageReceived = fun (envelope: AppEnvelope) -> (envelope.Message.ToString() |> printMessage )
}
let sendToAppWithTopic message =
async {
do! bus.PubSub.PublishAsync({AppEnvelope.Message = message}, "app.queue") |> Async.AwaitTask
// bus.Dispose()
} |> Async.Start
let subscribeToAppQueueWithoutTopic (callback : Subscription<AppEnvelope>) =
printfn "subscribe called"
bus.PubSub.Subscribe<AppEnvelope>(String.Empty, callback.OnMessageReceived)
(* ** Will not compile **
let subscribeAsyncToAppQueueWithTopic =
async {
do! bus.PubSub.SubscribeAsync<AppEnvelope>(String.Empty, callback.OnMessageReceived,
fun (x: ISubscriptionConfiguration) -> x.WithTopic "scanservice.queue")
|> Async.AwaitTask
} |> Async.Start
*)
// Will not compile
let subscribeToAppQueueWithTopic (callback : Subscription<AppEnvelope>) =
bus.PubSub.Subscribe<AppEnvelope>(String.Empty, callback.OnMessageReceived, (fun (x:ISubscriptionConfiguration) -> x.WithTopic("app.queue")), cts.Token)
subscribeToAppQueueWithoutTopic subscription |> ignore
sendToAppWithTopic "Testing"
Console.ReadKey() |> ignore
0
I don't know anything about EasyNetQ, but I think the problem here is that WithTopic returns a reference to the mutated configuration, which you need to explicitly ignore in F# in order to produce an Action<_>, like this:
let subscribeToAppQueueWithTopic (callback : Subscription<AppEnvelope>) =
bus.PubSub.Subscribe<AppEnvelope>(
String.Empty,
callback.OnMessageReceived,
(fun (x:ISubscriptionConfiguration) -> x.WithTopic("app.queue") |> ignore),
cts.Token)
Apparently, the API does this in order to provide a fluent C# interface:
/// <summary>
/// Allows publish configuration to be fluently extended without adding overloads
///
/// e.g.
/// x => x.WithTopic("*.brighton").WithPriority(2)
/// </summary>
public interface IPublishConfiguration
{
/// <summary>
/// Sets a priority of the message
/// </summary>
/// <param name="priority">The priority to set</param>
/// <returns>Returns a reference to itself</returns>
IPublishConfiguration WithPriority(byte priority);
/// <summary>
/// Sets a topic for the message
/// </summary>
/// <param name="topic">The topic to set</param>
/// <returns>Returns a reference to itself</returns>
IPublishConfiguration WithTopic(string topic);
From a functional programming perspective, this is a confusing way to do things, but such is life in the C# world, I suppose.

Put GLib.Array in a GLib.Value?

I can't figure out how to wrap a GLib.Array in a GLib.Value.
I tried this code.
public int main (string[] args) {
var value = Value(typeof (Array));
var a = new Array<string>();
a.append_val("test");
value.set_object((Object) a);
return 0;
}
But it resulted in these errors.
(process:1797): GLib-GObject-WARNING **: invalid uninstantiatable type '(null)' in cast to 'GObject'
(process:1797): GLib-GObject-CRITICAL **: g_value_set_object: assertion 'G_VALUE_HOLDS_OBJECT (value)' failed
I think of GValue being used as a container for a single type of value, whereas GArray is a collection. GValue does have a type_compatible () method. Using that method as a check before your code shows GLib doesn't allow a GArray to be stored as a GObject:
public int main (string[] args) {
if (!Value.type_compatible (typeof (Array), typeof (Object))) {
message ("Incompatible types");
return 1;
}
var value = Value(typeof (Array));
var a = new Array<string>();
a.append_val("test");
value.set_object((Object) a);
return 0;
}
This code stops where the check for compatible types is made.
I don't know what you are trying to achieve, but I suggest looking at GVariant:
void main () {
string[] a = {"test"};
Variant variant = a;
print (variant.print(true) + "\n");
}
If you need a GValue then you can store a GVariant in a GValue using GValue's take_variant () method.
GArray is not a GObject. However, it is a boxed type (a more primitive version of type tagging used in GValue), so you should be able to store it in the GValue using value.set_boxed (a).

MonoGame NullReferenceException on iOS

I'm trying to build a simple MonoGame app for iOS using F#. I have done this by manually cooking up a fsproj file, on the basis of project files for
F# iOS Single Page Application (template),
F# console application (template) and
C# iOS MonoGame (template).
My code looks like this:
namespace MonoGameFSharpTemplate
module Game =
open Microsoft.Xna.Framework
open Microsoft.Xna.Framework.Graphics
open Microsoft.Xna.Framework.Input
open Microsoft.Devices.Sensors
type Game1 () as x =
inherit Game()
do x.Content.RootDirectory <- "Content"
member val graphics = new GraphicsDeviceManager(x) with get, set
override x.Initialize() =
do base.Initialize()
override x.LoadContent() = ()
override x.Update (gameTime) =
do base.Update(gameTime)
override x.Draw (gameTime) =
do base.Draw(gameTime)
module App =
open UIKit
open Foundation
open Game
[<Register("AppDelegate")>]
type AppDelegate() =
inherit UIApplicationDelegate()
override val Window = null with get, set
override this.FinishedLaunching(app, options) =
use game = new Game1()
game.Run()
true
module Main =
open UIKit
[<EntryPoint>]
let main argv =
UIApplication.Main(argv, null, "AppDelegate")
0
It should be pretty much equivalent to the code provided in the C# template (which runs just fine, by the way).
When running this code in the iOS simulator, I get a NullReferenceException with the following stack trace
at Microsoft.Xna.Framework.Game.get_IsActive () [0x00000] in <d3066bb8224f42c4ab3ae66d66329856>:0
at Microsoft.Xna.Framework.iOSGamePlatform.Tick () [0x00006] in <d3066bb8224f42c4ab3ae66d66329856>:0
at Microsoft.Xna.Framework.iOSGameView.DoTick () [0x00000] in <d3066bb8224f42c4ab3ae66d66329856>:0
at (wrapper managed-to-native) UIKit.UIApplication:UIApplicationMain (int,string[],intptr,intptr)
at UIKit.UIApplication.Main (System.String[] args, System.IntPtr principal, System.IntPtr delegate) [0x00005] in /Users/builder/data/lanes/5024/152b654a/source/xamarin-macios/src/UIKit/UIApplication.cs:79
at UIKit.UIApplication.Main (System.String[] args, System.String principalClassName, System.String delegateClassName) [0x00038] in /Users/builder/data/lanes/5024/152b654a/source/xamarin-macios/src/UIKit/UIApplication.cs:63
at MonoGameFSharpTemplate.Main.main (System.String[] argv) [0x00000] in /Users/torbonde/Projects/MonoGameFSharpTemplate/MonoGameFSharpTemplate/Program.fs:47
I'm running the latest MonoGame build, v3.7.0.937, but I had the same issue using v3.6.
Does anyone know why I'm getting this error, and how to fix it? I can post the project file with references if necessary.

IDependencyResolver interface implementation in F# Web API

I am re-writing a C# ASP.NET Web API application in F#. I have Models and Controllers done and I moved onto MyDependencyResolver that implements IDependencyResolver.
I am having a problem implementing the GetService method, whose signature in C# is:
object GetService(System.Type serviceType)
So I need to return an obj and take a System.Type as a parameter.
This is what I have so far in F#:
type MyDependencyResolver() =
interface System.Web.Http.Dependencies.IDependencyResolver with
member this.BeginScope() : IDependencyScope =
this :> IDependencyScope
member this.GetService(serviceType:Type) : obj =
if (serviceType = typeof<Controllers.HomeController>) then
let homeController = new Controllers.HomeController(arg1, arg2, arg3, arg4)
homeController :> obj
// ???
elif (serviceType = typeof<_>) then
null
member this.GetServices (serviceType: Type) :IEnumerable<obj> =
let x = new List<obj>()
x :> IEnumerable<obj>
member this.Dispose() =
()
So if serviceType is of type HomeController I want to return an instance of HomeController, and if it's of any other type I want to return null. How do I do that in F#?
Edit:
GetService method in C#:
public object GetService(Type serviceType)
{
if (serviceType == typeof(Controllers.HomeController)){
return new Controllers.HomeController(arg1, arg2, arg3, arg4);
}
return null;
}
You could just use Activator.CreateInstance(serviceType) but where do you get the constructor arguments from?
In my projects I use Unity, which is configured as follows:
let private ConfigureUnity (config : HttpConfiguration) =
let rec unityResolver (container : IUnityContainer) =
{ new IDependencyResolver with
member this.BeginScope() =
unityResolver(container.CreateChildContainer()) :> IDependencyScope
member this.GetService serviceType =
try container.Resolve(serviceType) with
| :? ResolutionFailedException -> null
member this.GetServices serviceType =
try container.ResolveAll(serviceType) with
| :? ResolutionFailedException -> Seq.empty
member this.Dispose() = container.Dispose()
}
config.DependencyResolver <- (new UnityContainer())
.RegisterType<IFoo, FooImplementation>(new HierarchicalLifetimeManager())
.RegisterType<IBar, BarImplementation>(new HierarchicalLifetimeManager())
|> unityResolver
Classes (such as your controllers) are then resolved automatically and Unity will create dependencies (the constructor arguments) for you. Using other dependency injection frameworks should be straightforward.

Using F# type providers how do you implement a base constructor call as part of the constructor definition

What Im trying to do is create a provided type that calls its base constructor like this in C#:
public class SubclassController : BaseClass
{
public SubclassController (IntPtr handle) : base (handle)
{}
}
The closest I can currently get is this:
public sealed class SubclassController : BaseClass
{
public SubclassController (IntPtr handle)
{
this;
base..ctor (handle);
}
Which although having the same functionality is not entirely the same.
The code I am using to build the ProvidedConstructor is as follows:
let providedConstructor = ProvidedConstructor([ProvidedParameter("handle", typeof<IntPtr>)])
let ctorInfo = typeof<SubclassController>.GetConstructor(BindingFlags.Public ||| BindingFlags.Instance, null, [|typeof<IntPtr>|], null)
providedConstructor.BaseConstructorCall <- fun args -> ctorInfo, args
providedConstructor.InvokeCode <- fun args -> <## () ##>
It was actually a bug in ProvidedTypes.fs which has now been fixed in the latest version. It is available from the usual place at codeplex thanks to #desco
So this code is actually all thats needed for a correctly formed base constructor call:
let providedConstructor = ProvidedConstructor([ProvidedParameter("handle", typeof<IntPtr>)])
let ctorInfo = typeof<SubclassController>.GetConstructor(BindingFlags.Public ||| BindingFlags.Instance, null, [|typeof<IntPtr>|], null)
providedConstructor.BaseConstructorCall <- fun args -> ctorInfo, args
providedConstructor.InvokeCode <- fun args -> <## () ##>

Resources