I am using a third party API that rather clumsily makes use of ref parameters to produce outputs. Personally I really hate this design of an API but it's what I have available to me right now. I've had to hide the datatypes of the API slightly due to proprietary code but this should be irrelevant to the problem at hand.
Anyway in C# I can pass a null reference as a ref parameter successfully as follows:
IDataType tl = null;
bool success = api.myFunction(ref tl);
However in F# the following will not work
let mutable tl : IDataType = null //null reference assignment in F#
let success = api.myFunction(&tl) //& means ref in F#
It returns a null reference exception error. No such error is returned in C#.
Has anyone experiences this before? I am thinking it must be a bug in the API itself which is relatively ancient design.
**Edit: This should be closed, I believe the answer does not lie in the F# code but in the API as it's already a number of known bugs similar to this.
Quick and dirty prototyping of your API in C#
namespace API
{
public interface IDataType { void Hi(); }
public class API: IDataType {
public void Hi() { System.Console.WriteLine("Hi!"); }
public bool MyFunction(ref IDataType iface) {
iface = new API();
return true;
}
}
}
and then using it from F# exactly your way while staying within the same CLR:
let mutable iface : API.IDataType = null
if API.API().MyFunction(&iface) then iface.Hi()
works without any problem.
So, indeed, your problem is specific to your given API and has nothing to do with the form of its use from F#.
Using a ref cell is also an option here. Does this work?
let tl = ref null
let success = api.myFunction(tl)
The problem was with the API being compiled in .NET 2.0 which works fine under C# but not F#.
Related
If I have a C# 9 record defined:
public record Reading
{
public long Timestamp { get; init; }
public float TemperatureCelsius { get; init; }
}
How do I instantiate it from F# (5.01)?
let newReading () =
// ???
It feels like it should be simple, but I can't seem to get it to work.
I created two projects, both using .NET Core 5.0:
CSharpProj: C# 9 class library
FSharpProj: F# 5 console app
Instantiating the C# record from F# works fine for me, if I treat it like a normal class type:
open CSharpProj
let reading = Reading()
However, I'm unable to successfully set either Timestamp or TemperatureCelsius from F#. It looks like F# doesn't understand C# init setters yet. The following attempt compiles fine:
let reading = Reading(Timestamp = 1L, TemperatureCelsius = 1.0f)
But generates an InvalidProgramException at runtime. I assume the F# team will address this problem at some point. In the meantime, as a work-around, I changed the C# record type to:
public record Reading(long Timestamp, float TemperatureCelsius)
{
}
And now the same invocation from F# successfully sets the two properties.
I have below code in C#. And It is working Good.
WindowsIdentity winId = (WindowsIdentity)HttpContext.Current.User.Identity;
WindowsImpersonationContext ctx = winId.Impersonate();
ctx.Undo();
But i am tring to convert this code in F#. I have written below code.
Let winId = HttpContext.Current.User.Identity :> WindowsIdentity //Showing error
Let ctx = winId.Impersonate()
ctx.Undo()
In above code HttpContext.Current.User.Identity is not able cast in WindowsIdentity. Please let me know how can I do this.
The problem is that you're using the upcasting (:>) operator when you want to use the downcasting (:?>) operator. Upcasting is checked at compile time since you can always know if you can cast up the inheritance hierarchy, but casting down the hierarchy can fail, so it has a separate operator which can fail at runtime.
I am trying to convert this C# code to F#:
double[,] matrix;
public Matrix(int rows, int cols)
{
this.matrix = new double[rows, cols];
}
public double this[int row, int col]
{
get
{
return this.matrix[row, col];
}
set
{
this.matrix[row, col] = value;
}
}
Basically my biggest problem is creating the indexer in F#. I couldn't find anything that I could apply in this situation anywhere on the web. I included a couple of other parts of the class in case incorporating the indexer into a Matrix type isn't obvious. So a good answer would include how to make a complete type out of the three pieces here, plus anything else that may be needed. Also, I am aware of the matrix type in the F# powerpack, however I am trying to learn F# by converting C# projects I understand into F#.
Thanks in advance,
Bob
F# calls them "indexed properties"; here is the MSDN page. In F# they work slightly differently - each indexed property has a name.
However, there is a default one called "Item". So an implementation of your example would look like this:
member this.Item
with get(x,y) = matrix.[(x,y)]
and set(x,y) value = matrix.[(x,y)] <- value
Then this is accessed via instance.[0,0]. If you have named it something other than "Item", you would access it with instance.Something[0,0].
I'm working on a biztalk project and use a map to create the new message.
Now i want to map a datefield to a string.
I thought i can do it on this way with an Function Script with inline C#
public string convertDateTime(DateTime param)
{
return System.Xml.XmlConvert.ToString(param,ÿyyyMMdd");
}
But this doesn't work and i receive an error. How can i do the convert in the map?
It's a Biztalk 2006 project.
Without the details of the error you are seeing it is hard to be sure but I'm quite sure that your map is failing because all the parameters within the BizTalk XSLT engine are passed as strings1.
When I try to run something like the function you provided as inline C# I get the following error:
Object of type 'System.String' cannot be converted to type 'System.DateTime'
Replace your inline C# with something like the following:
public string ConvertDateTime(string param1)
{
DateTime inputDate = DateTime.Parse(param1);
return inputDate.ToString("yyyyMMdd");
}
Note that the parameter type is now string, and you can then convert that to a DateTime and perform your string format.
As other answers have suggested, it may be better to put this helper method into an external class - that way you can get your code under test to deal with edge cases, and you also get some reuse.
1 The fact that all parameters in the BizTalk XSLT are strings can be the source of a lot of gotchas - one other common one is with math calculations. If you return numeric values from your scripting functoids BizTalk will helpfully convert them to strings to map them to the outbound schema but will not so helpfully perform some very random rounding on the resulting values. Converting the return values to strings yourself within the C# will remove this risk and give you the expected results.
If you're using the mapper, you just need a Scripting Functiod (yes, using inline C#) and you should be able to do:
public string convertDateTime(DateTime param)
{
return(param.ToString("YYYYMMdd");
}
As far as I know, you don't need to call the System.Xml namespace in anyway.
I'd suggest
public static string DateToString(DateTime dateValue)
{
return String.Format("{0:yyyyMMdd}", dateValue);
}
You could also create a external Lib which would provide more flexibility and reusability:
public static string DateToString(DateTime dateValue, string formatPicture)
{
string format = formatPicture;
if (IsNullOrEmptyString(formatPicture)
{
format = "{0:yyyyMMdd}";
}
return String.Format(format, dateValue);
}
public static string DateToString(DateTime dateValue)
{
return DateToString(dateValue, null);
}
I tend to move every function I use twice inside an inline script into an external lib. Iit will give you well tested code for all edge cases your data may provide because it's eays to create tests for these external lib functions whereas it's hard to do good testing on inline scripts in maps.
This blog will solve your problem.
http://biztalkorchestration.blogspot.in/2014/07/convert-datetime-format-to-string-in.html?view=sidebar
Regards,
AboorvaRaja
Bangalore
+918123339872
Given that maps in BizTalk are implemented as XSL stylesheets, when passing data into a msxsl scripting function, note that the data will be one of types in the Equivalent .NET Framework Class (Types) from this table here. You'll note that System.DateTime isn't on the list.
For parsing of xs:dateTimes, I've generally obtained the /text() node and then parse the parameter from System.String:
<CreateDate>
<xsl:value-of select="userCSharp:GetDateyyyyMMdd(string(s0:StatusIdChangeDate/text()))" />
</CreateDate>
And then the C# script
<msxsl:script language="C#" implements-prefix="userCSharp">
<![CDATA[
public System.String GetDateyyyyMMdd(System.String p_DateTime)
{
return System.DateTime.Parse(p_DateTime).ToString("yyyyMMdd");
}
]]>
How do I use F#'s built-in support for async operations classes exposing the Event-based Asynchronous Pattern such as WebClient class?
let Download(url : Uri) =
let client = new WebClient()
let html = client.DownloadString(url)
html
When I try to change this to use "let!" in an async block (say as described in Soma's recent post)
let Download(url : Uri) =
async {
let client = new WebClient()
let! html = client.DownloadStringAsync(url)
return html }
I get an error message:
Type constraint mismatch. The type unit is not compatible with type Async<'a> The type 'unit' is not compatible with the type 'Async<'a>'
Edit: I'm really asking about the general question of using *Async() methods, WebClient is just an easy example. Microsoft says "... you should expose asynchronous features using the Event-based Asynchronous Pattern [ as opposed to BeginFoo()/EndFoo() ] whenever possible ..." so I would think there should be an easy way to consume an arbitrary *Async() method from F#.
The WebClient.DownloadStringAsync method is part of the .NET framework. It'll raise an event to signal its progress, and its return type is unit, so you don't want to use it, and there's no advantage in wrapping it in an async object.
The F# PowerPack defines an extension method, val webclient.AsyncDownloadString : uri -> Async{string}:
let Download(url : Uri) =
async {
let client = new WebClient()
client.Encoding <- Encoding.GetEncoding("utf-8")
let! html = client.AsyncDownloadString(url)
return html }
Unfortunately, the choice of name clashes with the existing webclient method, which can understandably cause confusion. However, I believe all of the F# async extensions begin with Async*.
[Edit to add in response to comments:]
Usually, .NET uses the BeginFoo / EndFoo pattern for concurrency. If the types are right, you can just use Async.BuildPrimitive beginMethod endMethod, which will return an Async wrapper for the method.
Sometimes objects don't use this pattern, like the WebClient, and you actually have to use Async.AwaitEvent to wait for an event to be fired, or write your own loop to repeatedly check to see if a bool is set. Here's a nice article on converting events to Async objects.
For what its worth, if you have F# installed, you should also have the source code which will give you an idea of how the F# team implements their async extensions. On my machine, the relevant file is located at:
C:\Program Files\FSharp-1.9.6.16\source\fsppack\FSharp.PowerPack\AsyncOperations.fs