I am working though Petzold's Creating Mobile Apps Using Xamarin Forms book, translating the C# code into F# where the F# code is not available on GitHub (he stopped posting FS after chapter 7). In chapter 9, page 189, he makes use of the Dependency attribute like this:
[assembly: Dependency(typeof(DisplayPlatformInfo.iOS.PlatformInfo))]
namespace DisplayPlatformInfo.iOS
{
public interface IPlatformInfo
{
string GetModel();
string GetVersion();
}
using System;
using UIKit;
using Xamarin.Forms;
public class PlatformInfo : IPlatformInfo
{
UIDevice device = new UIDevice();
//etc...
I want to do the equivalent in F#. I created the type and the only place I can add that attribute is at a generic do() statement:
type PlatformInfo () =
[<assembly: Dependency(typeof(Greetings.iOS.PlatformInfo))>]
do()
interface IPlatformInfo with
member this.GetModel () =
let device = new UIDevice()
device.Model.ToString()
member this.GetVersion () =
let device = new UIDevice()
String.Format("{0} {1}", device.SystemName, device.SystemVersion)
The problem is that I get a
warning: attributes are ignored in this construct.
How should I be placing this attribute into the type?
Assembly level attributes in F# need to be a in module, at the top level.
I would translate the C# above as:
namespace rec DisplayPlatformInfo.iOS
// Make a module specifically for this attribute
module DisplayPlatformAssemblyInfo =
[<assembly: Dependency(typeof(Greetings.iOS.PlatformInfo))>]
do ()
type IPlatformInfo =
abstract member GetModel : unit -> string
abstract member GetVersion : unit -> string
// ... Implement your type, etc
Since it is an assembly attribute, it should be place at the top level of a module instead of in a type. The following should be working:
[<assembly: Dependency(typeof(Greetings.iOS.PlatformInfo))>]
do ()
type PlatformInfo () =
// ...
Related
To improve performance in Blazor JS Interop calls, synchronous and unmarshalled apis are available
I struggle to find more information regarding the unmarshalled.
For example:
//javascript
JSFunctions.f1 = function (fields) {
var f1 = Blazor.platform.readStringField(fields, 0);
var f2 = Blazor.platform.readStringField(fields, 4);
var f3 = Blazor.platform.readStringField(fields, 8);
};
//F#
[<Inject>]
member val Js: IJSRuntime
let js = this.Js :?> IJSUnmarshalledRuntime
js.InvokeUnmarshalled<ElementReference, string, unit>("JSFunctions.f1", er, txt)
Where are the functions Blazor.platform.* defined?
Which one should be used to retrieve an argument of type ElementReference?
What is the second int parameter of the function readStringField and how should it be used?
Blazor object is a JavaScript object in global namespace (window) which added by blazor.webassembly.js in Blazor WebAssembly or blazor.server.js in Blazor Server. It added at the default template of Blazor Apps at the end of index.html (or _Host.cshtml) by following script:
<script autostart="false" src="_framework/blazor.webassembly.js"></script>
The Blazor object provide Blazor.platform and some useful api for example start() for manual start of Blazor.
This script also add another object named BINDING to global namespace (window.BINDING or simply BINDING).
They provide methods for working with .NET objects directly from JavaScript in unmarshalled way. for example you can read different type of data using
Blazor.platform.read....
You can read objects like ElementReference type object using:
Blazor.platform.readObjectField(fields,index)
Here fields is the input (struct or class) passed to JS function when you invoke it and index is its field offset in struct/class definition. You can read more about field offset in Microsoft documentations here.
Here is some example:
[StructLayout(LayoutKind.Explicit)]
public struct InteropStruct
{
[FieldOffset(0)]
public string Name;
[FieldOffset(8)]
public int Year;
}
You can also return a .Net object directly from JavaScript functions using BINDING as below:
return BINDING.js_string_to_mono_string(`Hello, ${name} (${year})!`);
You can discover more about these two objects in your browser developer tool for example by writing Blazor.platform. or BINDING.:
I used Dynamic Library in order to generate Lambda Expression that can be executed and return a content based on dynamic query prams,
my problem is with the context filter (using HasQueryFilter statement) that I need to ignore it before execute the query
I tried to use IgnoreQueryFilters, but isn't working with the IQueryable
IQueryable<object> EQueryableItems = (IQueryable<object>)typeof(ApplicationDbContext).GetProperty("Users-Table").GetValue(_appDbContext, null)
IQueryable<object> QueryResult = (IQueryable<object>) EQueryableItems.Where("Id > 1500");
EQueryableItems will contain data based on the context query, I need to get all data not just the result of the filter.
EF Core specific queryable extension methods are available for IQueryable<object>, hence it can be used with the provided code:
IQueryable<object> EQueryableItems = ...;
EQueryableItems = EQueryableItems.IgnoreQueryFilters(); // <-- defined and works
However, if you want to work with non generic IQueryable interface, you can create and use a custom extension method similar to
using System.Linq;
using System.Linq.Expressions;
namespace Microsoft.EntityFrameworkCore
{
public static class CustomQueryableExtensions
{
public static IQueryable IgnoreQueryFilters(this IQueryable source) =>
source.Provider.CreateQuery(Expression.Call(
typeof(EntityFrameworkQueryableExtensions),
nameof(EntityFrameworkQueryableExtensions.IgnoreQueryFilters),
new[] { source.ElementType },
source.Expression));
}
}
which would enable usage of
IQueryable EQueryableItems = ...;
EQueryableItems = EQueryableItems.IgnoreQueryFilters(); // <-- custom defined and works
You can add similar custom extensions methods for other EF Core specific IQueryable<T> extension methods like AsNoTracking(), AsTracking(), AsSplitQuery() etc. if needed, using the same pattern as the above implementation.
I'm developing a plugin-loading system for my F# .NET 5 app, following this Microsoft guide. I wanted to provide an interface ICore that would have some internal, opaque state type that I would provide an interface for manipulating.
In Scala, I might do this like
trait ICore {
type State
def reset: State
}
and then call this method like
def resetCoreState(c: Core): c.State = c.reset
and implement a core like
object StringCore extends ICore {
override type State = String
override def reset: String = ""
}
however F# doesn't have this feature.
How should I design my interface,
type ICore() =
interface
// abstract type State
abstract method reset : State
end
let resetCoreState : ???
type StringCore() = ???
so that plugins can manage their own state?
I don't think there's any simple way to make the state type opaque, but here's how I would define these types in F#:
type ICore<'state> =
abstract member Reset : 'state
type StringCore() =
interface ICore<string> with
member __.Reset = ""
let resetCoreState (core : ICore<_>) =
core.Reset
I know that dynamic libraries can be loaded by Poco::SharedLibrary as below:
using PocoLibraryPtr = std::shared_ptr<Poco::SharedLibrary>;
poco_library = PocoLibraryPtr(new Poco::SharedLibrary(library_path));
I see in the code that the class is instantiated directly after loading. Is this feasible? Currently this code works fine.
template <typename ClassObject, typename Base>
class ClassFactory : public AbstractClassFactory<Base> {
public:
ClassFactory(const std::string& class_name,
const std::string& base_class_name)
: AbstractClassFactory<Base>(class_name, base_class_name) {}
Base* CreateObj() const { return new ClassObject; }
};
When the class is loaded, then the code use
classobj = factory->CreateObj();
to create the class. I did not find similar usage online. Is there any code I didn't notice?
It looks like you want a shared library to create an object using a templatized factory class.
Template instantiations are static polymorphic so the factory object needs to be determined at compile time.
In other words, no, that won't work.
If you specifically want Poco SharedLibrary help, take a look at the Poco documentation for more help: https://pocoproject.org/docs/Poco.SharedLibrary.html.
Or look at the slides here: https://pocoproject.org/slides/120-SharedLibraries.pdf
Suppose I have the following simple wrapper of a NativeClassInstance.
public ref class Wrapper
{
private:
NativeClass *_wrapped;
public:
Renderer()
{
_wrapped = new NativeClass();
}
~Renderer()
{
delete _wrapped;
}
operator NativeClass*()
{
return _wrapped;
}
}
Now, I want to create an instance of Wrapper from C# with Wrapper wrapper = new Wrapper() and use it in another native functionalities wrapper that resides in another assembly with Helper.Foo(wrapper) (nothing strange having other functionalities not directly related to the wrapped classes in another assembly, IMO):
// Utilities is in another Assembly
public ref class Helper
{
public:
static Foo(Wrapper ^wrapper)
{
// Do something in native code with wrapper->_wrapped
}
}
The results with the implicit user conversion is:
candidate function(s) not accessible
If I make _wrapped public it is:
cannot access private member declared in class ...
Now, I've learnt that native type visibility is private outside of the assembly. So, how I'm supposed to use the wrapped entity in native code outside the assembly it's defined? I've read of make_public but you can't use with template types so it seems very limiting in the general case. Am I missing something? Is there a more correct solution?
I haven't been able to successfully expose native types using make_public, however a solution I have used is to put NativeClass in its own native DLL and then a) reference the native DLL from both assemblies; and b) pass the pointer to the native class around as an IntPtr.
Under the above scenario, instead of having an operator NativeClass* you might use a property such as
property IntPtr WrappedObject {
IntPtr get() { return IntPtr(_wrapped); }
}
You then retrieve NativeObject in you helper assembly by
static void Foo(Wrapper ^wrapper)
{
NativeObject *_wrapped
= static_cast<NativeObject*>(wrapper->WrappedObject.ToPointer());
// ... do something ...
}
If you use make_public, your solution of making _wrapped public should work (it would obviously be best to make a public accessor instead). Regarding your comment "I've read of make_public but you can't use with template types so it seems very limiting in the general case." I agree--read here for the workaround I used:
http://social.msdn.microsoft.com/Forums/en-US/vclanguage/thread/b43cca63-b0bf-451e-b8fe-74e9c618b8c4/
More related info:
Best workaround for compiler error C2158: make_public does not support native template types
Good luck!