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
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.
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).
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.
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.
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 -> <## () ##>