In converting a project to .NET Standard 2.0, FSharpFunc<T, TResult>. FromConverter method from the FSharp.Core library is not available anymore. Is there a way to convert this code to a .NET Standard 2.0 FSharp.Core implementation?
async Task<Unit> RunProcess(FSharpMailboxProcessor<T> mailbox, Func<T, Task> process) { ... }
public BaseMailboxProcessor(Func<TFuncInput, Task> process, Action<Exception, TFuncInput> errorHandler = null, CancellationToken? cancellationToken = null)
{
m_ErrorHandler = errorHandler;
m_TokenSource = cancellationToken.HasValue ? CancellationTokenSource.CreateLinkedTokenSource(cancellationToken.Value) :
new CancellationTokenSource();
var cancellationOption = FSharpOption<CancellationToken>.Some(m_TokenSource.Token);
Converter<FSharpMailboxProcessor<TMailboxInput>, FSharpAsync<Unit>> converter = (mailbox) =>
{
return FSharpAsync.AwaitTask<Unit>(RunProcess(mailbox, process));
};
m_Mailbox = new FSharpMailboxProcessor<TMailboxInput>(FSharpFunc<FSharpMailboxProcessor<TMailboxInput>, FSharpAsync<Unit>>.FromConverter(converter), cancellationOption);
m_Mailbox.Start();
}
You should be able to use FuncConvert.ToFSharpFunc, this appears to still be present in the netstandard version of FSharp.Core.
You can trivially define your own:
let ToFSharpFunc (converter: System.Func<_, _>) = fun t -> converter.Invoke t
Also, if you need to use an FSharpFunc in C# you can simply call .Invoke on it where .Invoke on the FSharpFunc object is a Func.
Related
I am using a software framework which on its part uses log4j-2.7 (I can't update the jars of the framework).
I have written a third party library which provides a RewritePolicy to re-format the log messages. The library uses log4j-2.7 as well.
Within the framework I do some loggings with MapMessage. However, the rewrite policy receives them as SimpleMessage or some other types of Message, but not as MapMessage.
Here is code examples from framwork:
var mapMessage = new MapMessage()
mapMessage.put("first", "first")
mapMessage.put("second", "second")
logger.info(mapMessage)
And here the rewrite method of the RewritePolicy:
#Override
public LogEvent rewrite(LogEvent source) {
final Message modifiedMessage;
Message origMessage = source.getMessage();
if (origMessage instanceof MapMessage) {
Map<String, Object> map = new HashMap<String, Object>(((MapMessage) origMessage).getData());
modifiedMessage = new SimpleMessage(createStringMessage((HashMap<String, Object>) map));
} else {
modifiedMessage = origMessage;
}
LogEvent modifiedLogEvent = new Log4jLogEvent.Builder(source).setMessage(modifiedMessage).build();
return modifiedLogEvent;
}
My problem was due to the fact that the sofware platform mentioned in my post did migrate from log4j 1 to 2, and as explained here https://logging.apache.org/log4j/2.x/manual/migration.html, I had to change the package from org.apache.log4j to org.apache.logging.log4j.
I'm new to F# and trying to translate some C# ASP.NET Core code into F#
There is a C# controller here, and a working translated F# controller here
even though I got it working, I can't seem to figure out how to make the controller actions async. The methods call async code on a Commands object and a Queries object that are injected. The Commands and Queries are currently implemented in C#.
So for example a couple of the async C# controller methods are:
public async Task<IEnumerable<ToDoItem>> Get()
{
return await queries.GetAll();
}
[HttpGet("{id}", Name = "GetTodo")]
public async Task<IActionResult> GetById(string id)
{
var item = await queries.Find(id);
if (item == null)
{
return NotFound();
}
return new ObjectResult(item);
}
public async Task<IActionResult> Create([FromBody] ToDoItem item)
{
if (item == null)
{
return BadRequest();
}
if (string.IsNullOrEmpty(item.Id)) item.Id = Guid.NewGuid().ToString();
await commands.Add(item);
return CreatedAtRoute("GetTodo", new { id = item.Id }, item);
}
and I've translated those to F# like this:
[<HttpGet>]
member __.Get() =
__.Queries.GetAll() // this should be awaited
[<HttpGet("{id}", Name = "GetFSTodo")>]
member __.GetToDoItem(id) =
let data = __.Queries.Find(id) // this should be awaited
if isNull data
then __.NotFound() :> IActionResult
else
new ObjectResult(data) :> IActionResult
[<HttpPost>]
member __.Create([<FromBody>] item:ToDoItem) =
item.Id <- Guid.NewGuid().ToString()
(__.Commands.Add(item)) |> ignore // this should be awaited
let rv = new RouteValueDictionary()
rv.Add("id",item.Id)
__.CreatedAtRoute("GetTodo", rv, item) :> IActionResult
These methods work but I think they are not correctly done since they aren't awaiting the async calls on Queries and Commands. I've thrashed for some hours with trial and error but every attempt I've made to make the controller methods async results in them not returning any data to the browser even though they return a 200 status code. You can see some of my attempts commented out in the F# controller
Hoping some F# guru(s) could help me translate those methods correctly. There are some pretty bad tooling issues currently in terms of F# with ASP.NET Core which makes it more difficult for a newbie like me. I've mentioned those issues in the readme
There are a few additional methods in the code but I figure if I can learn how to solve for these methods then the same solution will probably apply to the other methods.
The code is in a public repository so you can easily try it in VS 2015 as long as you have the latest VS updates and the latest ASP.NET Core tooling installed
UPDATE:
thanks to the linked post by Mark Seemann, I was able to get this method working async
[<HttpGet("{id}", Name = "GetFSTodo")>]
member __.GetToDoItem(id) =
async {
let! data = __.Queries.Find(id) |> asyncReturn
if isNull data
then return __.NotFound() :> IActionResult
else
return new ObjectResult(data) :> IActionResult }
|> Async.StartAsTask
by using the helper function
let asyncReturn x = async { return x }
I'm still struggling with this method
[<HttpGet>]
member __.Get() =
async {
let! data = __.Queries.GetAll() |> asyncReturn
return data }
|> Async.StartAsTask
which is translated from this C# method:
[HttpGet]
public async Task<IEnumerable<ToDoItem>> Get()
{
return await queries.GetAll();
}
the async F# method works but it produces different json output than the C# version
C#
[{"id":"4f4e1596-6a48-4854-9982-7a2568aa1b1b","title":"add input validation","isDone":false,"dateAdded":"2016-09-20T21:16:04.8791044Z"},{"id":"9929b657-6a53-40b6-8c1c-1e4d0db593cd","title":"make F# controller async","isDone":false,"dateAdded":"2016-09-21T19:36:44.6650776Z"},{"id":"5bb5f544-6289-4051-ad65-d0dc016128e7","title":"learn F# basics","isDone":true,"dateAdded":"2016-09-22T11:59:00"},{"id":"e5e06118-c49f-496a-8175-9719ea72beed","title":"monkey business","isDone":false,"dateAdded":"2016-09-22T16:22:20.3133161Z"},{"id":"af0db8f2-6b49-4e31-86fa-e27c8e091f42","title":"funky bidness","isDone":false,"dateAdded":"2016-09-22T16:23:35.1175195Z"}]
F#
{"result":[{"id":"4f4e1596-6a48-4854-9982-7a2568aa1b1b","title":"add input validation","isDone":false,"dateAdded":"2016-09-20T21:16:04.8791044Z"},{"id":"9929b657-6a53-40b6-8c1c-1e4d0db593cd","title":"make F# controller async","isDone":false,"dateAdded":"2016-09-21T19:36:44.6650776Z"},{"id":"5bb5f544-6289-4051-ad65-d0dc016128e7","title":"learn F# basics","isDone":true,"dateAdded":"2016-09-22T11:59:00"},{"id":"e5e06118-c49f-496a-8175-9719ea72beed","title":"monkey business","isDone":false,"dateAdded":"2016-09-22T16:22:20.3133161Z"},{"id":"af0db8f2-6b49-4e31-86fa-e27c8e091f42","title":"funky bidness","isDone":false,"dateAdded":"2016-09-22T16:23:35.1175195Z"}],"id":65,"exception":null,"status":5,"isCanceled":false,"isCompleted":true,"creationOptions":0,"asyncState":null,"isFaulted":false}
so I still could use some help on how to make the F# version produce the expected output
UPDATED 2016-09-28
Thanks to Ruben Bartelink this is what my controller looks like now correctly implemented as async and handling the nuances that differ between C# and F# async patterns:
namespace FSharp.WebLib
open System
open Microsoft.AspNetCore.Mvc
open Microsoft.AspNetCore.Routing
open Microsoft.AspNetCore.JsonPatch
open FSharp.Models
module ActionResult =
let ofAsync (res: Async<IActionResult>) =
res |> Async.StartAsTask
[<Route("api/[controller]")>]
type FSToDoController(commands: IToDoCommands, queries: IToDoQueries) =
inherit Controller()
[<HttpGet>]
member this.Get() =
ActionResult.ofAsync <| async {
let! data = queries.GetAll()
return JsonResult(data) :> _ }
[<HttpGet("{id}", Name = "GetFsToDo")>]
member this.Get(id) =
ActionResult.ofAsync <| async {
let! res = queries.Find id
match res with
| None -> return this.NotFound() :> _
| Some data -> return ObjectResult(data) :> _ }
// create
[<HttpPost>]
member this.Post([<FromBody>] item:ToDoItem) =
ActionResult.ofAsync <| async {
if not this.ModelState.IsValid then
return this.BadRequest() :> _
else
let item = { item with Id = Guid.NewGuid() |> string }
do! commands.Add item
let rv = RouteValueDictionary()
rv.Add("id",item.Id)
return this.CreatedAtRoute("GetFsToDo", rv, item) :> _ }
// update
[<HttpPut("{id}")>]
member this.Put(id:String, [<FromBody>] item:ToDoItem) =
ActionResult.ofAsync <| async {
if (not this.ModelState.IsValid) || String.IsNullOrEmpty item.Id then
return this.BadRequest() :> _
else
let! res = queries.Find id
match res with
| None -> return this.NotFound() :> _
| Some toDo ->
do! commands.Update item
return NoContentResult() :> _ }
for anyone else interested in learning F# particularly for use in ASP.NET Core, this is part of a proof of concept project on github that has both C# and F# implementations of a ToDo list back end web api both of which are consumed from a front end implemented with polymer web components. Models and data access are also implemented in both languages to provide a good comparison for C# devs like myself to learn F#
Becuase monotouch compile to native code, so it has some limitation such as dynamic invoke is not allowed.
But I have a lot class in .net, that I use the ChannelFactory dynamic to invoke the wcf service: new ChannelFactory(myBinding, myEndpoint); Now in monotouch I should use the slsvcutil to generate the wcf proxy class, but the slsvcutil generate a lot of Unnecessary extra code (huge), and Makes consumers difficult to unit test, due to high coupling with the WCF infrastructure through the ClientBase class.
Is there a better solution except the ChannelFactory? I would rather write the code manually, have more control over how services are invoked such as the ChannelFactory.
==========
ChannelFactory<IMyContract> factory = new ChannelFactory<IMyContract>(binding, endpointAddress);
return factory.CreateChannel();
//==> It throw exception: MonoTouch does not support dynamic proxy code generation. Override this method or its caller to return specific client proxy instance
ChannelFactory<T> has a virtual method CreateChannel(). If this is not overridden, it uses dynamic code generation, which fails on MonoTouch.
The solution is to override it and provide your own compile-time implementation.
Below is an old service implementation of mine that at least used to work on MonoTouch. I split it up into 2 partial classes - the first one being linked in all builds, the 2nd only in the iOS builds (allowing the dynamic generation mechanism to still work on windows).
I've stripped it down to only contain 1 service call.
TransactionService.cs:
public partial class TransactionService : ClientBase<IConsumerService>, IConsumerService
{
public TransactionService()
{
}
public TransactionService(string endpointConfigurationName) :
base(endpointConfigurationName)
{
}
public TransactionService(string endpointConfigurationName, string remoteAddress) :
base(endpointConfigurationName, remoteAddress)
{
}
public TransactionService(string endpointConfigurationName, EndpointAddress remoteAddress) :
base(endpointConfigurationName, remoteAddress)
{
}
public TransactionService(Binding binding, EndpointAddress remoteAddress) :
base(binding, remoteAddress)
{
}
public AccountBalanceResponse GetAccountBalance( AccountBalanceQuery query )
{
return Channel.GetAccountBalance( query );
}
}
TransactionService.iOS.cs:
ConsumerServiceClientChannel which executes the calls via reflection)
public partial class TransactionService
{
protected override IConsumerService CreateChannel()
{
return new ConsumerServiceClientChannel(this);
}
private class ConsumerServiceClientChannel : ChannelBase<IConsumerService>, IConsumerService
{
public ConsumerServiceClientChannel(System.ServiceModel.ClientBase<IConsumerService> client) :
base(client)
{
}
// Sync version
public AccountBalanceResponse GetAccountBalance(AccountBalanceQuery query)
{
object[] _args = new object[1];
_args[0] = query;
return (AccountBalanceResponse)base.Invoke("GetAccountBalance", _args);
}
// Async version
public IAsyncResult BeginGetAccountBalance(AccountBalanceQuery query, AsyncCallback callback, object asyncState )
{
object[] _args = new object[1];
_args[0] = query;
return (IAsyncResult)base.BeginInvoke("GetAccountBalance", _args, callback, asyncState );
}
public AccountBalanceResponse EndGetAccountBalance(IAsyncResult asyncResult)
{
object[] _args = new object[0];
return (AccountBalanceResponse)base.EndInvoke("GetAccountBalance", _args, asyncResult);
}
}
}
EDIT: I just tested this with the latest MT (5.2) - it no longer needs all that extra boiler plate I had in there before, just the CreateChannel() override. I've cleaned up the sample code to match.
EDIT2: I added an async method implementation.
I think you might be confusing terms here - ChannelFactory is a generic type, not a dynamic.
According to MonoTouch documentation, although there's limitations to the Generics support in MonoTouch, ChannelFactory should be okay here.
Have you tried using ChannelFactory?
Is there a way to set the timeout for CreateSprocAccessor(...) in Enterprise Library 5.0?
Cause the default timeout is not working for long stored procedures.
First thing: adding a timeout in the connection string doesn't solve the problem.
I found a workaround: You can modify the source code of EL 5.0 and generate a new custom DLL.
in ...\EntLib50Src\Blocks\Data\Src\Data\SprocAccessor.cs
in Execute(...) method
add this code just before return: command.CommandTimeout = 120; // 2 mins
Compile and use the new Microsoft.Practices.EnterpriseLibrary.Data.dll that you can find in ...\EntLib50Src\Blocks\bin\Debug
actually, I think there is no need to have your own copy of EL. In order to keep original EL binaries unchanged, you just can do the follow:
inherit from SprocAccessor class
overwrite Execute() method, put here the same code as in SprocAccessor.Execute() but adding the timeout part
you will need also to keep in local variable (in your new class) procedureName as this variable is private in SprocAccessor class
some thing like this:
public class SprocAccessorWithTimeout<T> : SprocAccessor<T>
{
readonly string procedureName;
public SprocAccessorWithTimeout(Database database, string procedureName, IRowMapper<T> rowMapper) : base(database, procedureName, rowMapper)
{
this.procedureName = procedureName;
}
public override IEnumerable<T> Execute(params object[] parameterValues)
{
using (var command = Database.GetStoredProcCommand(this. procedureName))
{
command.CommandTimeout = MaxSpExecutionTimeout;
if (parameterValues.Length > 0)
{
Database.AssignParameters(command, parameterValues);
}
return base.Execute(command);
}
}
}
I was trying to use Unity 2.0 beta 2 for Silverlight in my Windows Phone 7 project and I kept getting this crash:
Microsoft.Practices.Unity.Silverlight.dll!Microsoft.Practices.ObjectBuilder2.DynamicMethodConstructorStrategy.DynamicMethodConstructorStrategy() + 0x1f bytes
Microsoft.Practices.Unity.Silverlight.dll!Microsoft.Practices.ObjectBuilder2.DynamicMethodConstructorStrategy.DynamicMethodConstructorStrategy() + 0x1f bytes mscorlib.dll!System.Reflection.RuntimeConstructorInfo.InternalInvoke(System.Reflection.RuntimeConstructorInfo rtci = {System.Reflection.RuntimeConstructorInfo}, System.Reflection.BindingFlags invokeAttr = Default, System.Reflection.Binder binder = null, object parameters = {object[0]}, System.Globalization.CultureInfo culture = null, bool isBinderDefault = false, System.Reflection.Assembly caller = null, bool verifyAccess = true, ref System.Threading.StackCrawlMark stackMark = LookForMyCaller)
mscorlib.dll!System.Reflection.RuntimeConstructorInfo.InternalInvoke(object obj = null, System.Reflection.BindingFlags invokeAttr = Default, System.Reflection.Binder binder = null, object[] parameters = {object[0]}, System.Globalization.CultureInfo culture = null, ref System.Threading.StackCrawlMark stackMark = LookForMyCaller) + 0x103 bytes
mscorlib.dll!System.Activator.InternalCreateInstance(System.Type type = {Name = "DynamicMethodConstructorStrategy" FullName = "Microsoft.Practices.ObjectBuilder2.DynamicMethodConstructorStrategy"}, bool nonPublic = false, ref System.Threading.StackCrawlMark stackMark = LookForMyCaller) + 0xf0 bytes mscorlib.dll!System.Activator.CreateInstance() + 0xc bytes
Microsoft.Practices.Unity.Silverlight.dll!Microsoft.Practices.ObjectBuilder2.StagedStrategyChain.AddNew(Microsoft.Practices.Unity.ObjectBuilder.UnityBuildStage stage = Creation) + 0x1d bytes
Microsoft.Practices.Unity.Silverlight.dll!Microsoft.Practices.Unity.UnityDefaultStrategiesExtension.Initialize() + 0x6c bytes
Microsoft.Practices.Unity.Silverlight.dll!Microsoft.Practices.Unity.UnityContainerExtension.InitializeExtension(Microsoft.Practices.Unity.ExtensionContext context = {Microsoft.Practices.Unity.UnityContainer.ExtensionContextImpl}) + 0x31 bytes
Microsoft.Practices.Unity.Silverlight.dll!Microsoft.Practices.Unity.UnityContainer.AddExtension(Microsoft.Practices.Unity.UnityContainerExtension extension = {Microsoft.Practices.Unity.UnityDefaultStrategiesExtension}) + 0x1a bytes
Microsoft.Practices.Unity.Silverlight.dll!Microsoft.Practices.Unity.UnityContainer.UnityContainer() + 0xf bytes
Thinking I could resolve it I've tried a few things but to no avail.
Turns out that this is a rather fundamental problem and my assumption that Windows Phone 7 is Silverlight 3 + Some other stuff is wrong. This page describes the differences between Mobile Silverlight and Silverlight 3.
Of particular interest is this:
The System.Reflection.Emit namespace is not supported in Silverlight for Windows Phone.
This is precisely why Unity is crashing on the phone, DynamicMethodConstructorStrategy class uses System.Reflection.Emit quite extensively...
So the question is, what alternative to Unity is there for Windows Phone 7?
So, in the spirit of answering my own questions, I've put together a simple DI container (using Activator.CreateInstance for instantiating things). All this does is support type registrations and instance registrations.
Seems to be doing the job. Will worry about performance later.
public class DuplicateRegistrationException : Exception {
public DuplicateRegistrationException() { }
public DuplicateRegistrationException(string message) : base(message) { }
public DuplicateRegistrationException(string message, Exception inner) : base(message, inner) { }
}
public interface IDIContainer {
void Register<TIntf, TClass> () where TIntf: class where TClass : TIntf;
TIntf Resolve<TIntf>() where TIntf : class;
void RegisterInstance<TIntf>(TIntf instance);
}
public class DIContainer : IDIContainer{
Dictionary<Type, Type> m_TypeRegistrations;
Dictionary<Type, object> m_InstanceRegistrations;
public DIContainer() {
m_TypeRegistrations = new Dictionary<Type, Type>();
m_InstanceRegistrations = new Dictionary<Type, object>();
}
#region IDIContainer Members
public void Register<TIntf, TClass>()
where TIntf : class
where TClass : TIntf {
if(DoesRegistrationExist<TIntf>())
throw new DuplicateRegistrationException("Can only contain one registration per type");
m_TypeRegistrations.Add(typeof(TIntf), typeof(TClass));
}
public TIntf Resolve<TIntf>() where TIntf : class {
return Resolve(typeof(TIntf)) as TIntf;
}
private object Resolve(Type type) {
if(!m_TypeRegistrations.ContainsKey(type)) {
if(!m_InstanceRegistrations.ContainsKey(type))
throw new NotSupportedException("Cannot find registration for type " + type.FullName + ".");
else
return m_InstanceRegistrations[type];
} else {
var createdType = m_TypeRegistrations[type];
ConstructorInfo[] constructors = createdType.GetConstructors();
ConstructorInfo mostSpecificConstructor = null;
foreach(var c in constructors) {
if(mostSpecificConstructor == null || mostSpecificConstructor.GetParameters().Length < c.GetParameters().Length) {
mostSpecificConstructor = c;
}
}
List<object> constructorParameters = new List<object>();
foreach(var a in mostSpecificConstructor.GetParameters()) {
constructorParameters.Add(Resolve(a.ParameterType));
}
return Activator.CreateInstance(createdType, constructorParameters.ToArray());
}
}
private bool DoesRegistrationExist<T>() {
return m_InstanceRegistrations.ContainsKey(typeof(T)) || m_TypeRegistrations.ContainsKey(typeof(T));
}
public void RegisterInstance<TIntf>(TIntf instance) {
if(DoesRegistrationExist<TIntf>()) {
throw new DuplicateRegistrationException("Can only contain one registration per type");
}
m_InstanceRegistrations.Add(typeof(TIntf), instance);
}
#endregion
Funq has been in development for over a year and now has a 1.0 release. It's designed to be fast and run under Compact Framework and Windows Phone 7. Another big advantage is that the author has done great a screencast series explaining its development process using TDD which is very informative!
As an aside, the most recent performance tests that I can find are from March 2009 showing it beating the pants off Unity, Autofac, Ninject, and StructureMap. I'm trying to locate more recent tests and will update this post if I do.
If you cannot find an IOC container that works on Windows Phone 7 (and I wouldn't be surprised you cannot) then I'd suggest going with a different DI strategy.
I just started putting together a Windows Phone 7 Extension Tools project on codeplex. The current version checked in supports IoC with implicit DI along with the Common Service Locator to allow complete abstraction of your code and the container they use.
Check it out over at:
http://wp7.codeplex.com
Cheers,
Simon Hart
The OpenNETCF.IoC framework works on Windows desktop, Mono, Windows Mobile, Windows Phone 7 and MonoTouch. I'm a fan of code reuse.
It's modelled after the SCSF/CAB (in object model, not crappy perf), so many of those tutorials are valid and you can leverage existing knowledge and code assets.
Despite Mark Seeman says "the world doesn’t need yet another container" in his excellent book "Dependency Injection in .NET", I decided to implement my own DI container for WP7 which provides the major DI features:
object composition
lifetime management
interception which allows you to aspect-oriented programming approaches
The container is the part of PhoneCore Framework, which you can find here:
http://phonecore.codeplex.com