Accessing library internal fields with mirror - dart

Trying to access a private (package internal) field got me in a strange situation.
My Class "Properties" has a internal field named '_forceAccum'.
Trying to get the value of it fails for me using this code:
InstanceMirror bodyMirror = reflect(props);
var value = propsMirror.getField(new Symbol('_forceAccum'));
but if I use this instead:
InstanceMirror bodyMirror = reflect(props);
var value = propsMirror.getField(new Symbol('_forceAccum#434525364'));
it works. (I got the "#..." from iterating through the symbols (.toString()) from the class mirror).
Is it supposed to work this way? Is it safe or will it change in the next version? (I'm using 1.7.2)
or does it just work by pure happenstance?

Your problem is that you have a library private name. It's name isn't just _forceAccum, it's a special symbol related to _forceAccum that is unique to the library, but different from a _forceAccum in another library.
To create the private symbol using mirrors, you must use MirrorSystem.getSymbol as: MirrorSystem.getSymbol("_forceAccum", libraryMirrorOfLibrary). This creates a library-private symbol for that particular library. You can't create a private symbol without either specifying the library that it's private to, or by being in the library (#_forceAccum will create the correct symbol for the library that it occurs in).
The other alternative, which you used, is to look through the library and find the already existing symbol there:
var forceAccumSymbol =
libraryMirrorOfLibrary.declarations.keys
.where((n) => MirrorSystem.getName(n) == "_forceAccum")
.first;
(if the declaration is a top-level declaration).
The _forceAccum#something name that you are seeing is the VM's way of making a name library private. It's not going to work if compiled with dart2js, and it's probably not going to have the same something on each run, so you can't can't put it into your code.

The behavior is not guaranteed.
If you were in the same library you could probably build the symbol yourself (either with #_forceAccum or with const Symbol("_forceAccum") or new Symbol("_forceAccum")).
The best way to get to the symbol from outside its library is probably to find it (testing with toString() and then cache it.

Related

Instantiating a class by String name in Dart

I am trying to call a method of a class that I only know by name as a String. Now therefore I would need a ClassMirror of that class that allowes me to instantiate an instance. However, creating ClassMirrors seems to be only possible by entering a type using reflectClass(Type) or by passing an already existing instance of that class into reflect(dynamic). So these aren`t helping if I only have a String.
In Java you can do this pretty easily, by calling Class.forName(String). Then you would get a Constructor instance, make it accessibly and call it.
Does anyone know if this is even possible in dart? What seems weird is that once you have a ClassMirror you can access fields and methods by passing symbols, which can be created by Strings.
You can put a specific list of strings to map to a specific list of closures to create a new object with specific parameters.
But you can't get a reflection without using dart:mirrors, which is being deprecated, and also had a negative impact on tree shaking to get the payload size down.
In general, you're invited to look at the package:reflectable to achieve most of what you'd want out of dart:mirrors, using source-to-source builders.

Using CompilerMessageAttribute to produce a compiler error, but only in other assemblies

I have a union type that has a single, empty case.
type Default =
| Default
This type has a purpose, but it's not meant to be visible or usable.
Unfortunately, I have to use it in an inline function that does need to be visible. This prevents me from making the type or the case private.
The solution I came up with is using the CompilerMessageAttribute on it to signal an error whenever it's used. This would be fine, but now I can't compile my own assembly because IT uses it.
Is there a way to signal an error only when it's used by an assembly that references my assembly?
Let me reiterate the requirements to make sure I understand them:
The type needs to be public, so that that other assemblies can reference it implicitly via inline.
But if other assemblies reference it explicitly, then that is an error.
I don't know of any way of doing this using standard tooling.
I can see two possible solutions.
If only one calling assembly needs to use the inline function, what about making the type internal and then have the calling assembly be a friend assembly, using the InternalsVisibleToAttribute.
The only other alternative I can think of is security by obscurity. Hide the type in some awkwardly named module and require module qualification. This will stop accidental use of the type, if nothing else.
You could even add a build step to check that no source code references the module name.
[<RequireQualifiedAccessAttribute>]
module ``Dont Use This`` =
type Default =
| Default
let x = ``Dont Use This``.Default
And yes, it's very kludgy.

F# using a class instance's member functions

I'm trying to create a connection to open a database over ODBC. I cannot figure out how to execute an objects member functions. The code:
let DbConnection = new System.Data.Odbc.OdbcConnection()
DbConnection.open
The errors I get are: Missing qualification after '.'
or sometimes: unexpected identifier in implementation file
Does anybody know what is wrong with my syntax?
I suppose you wanted something like this:
let dbConnection = new System.Data.Odbc.OdbcConnection()
dbConnection.Open()
The problems are:
F# is case sensitive so you need Open rather than open (also open is a language keyword, so if you wanted to use it as a name, you'd have to write ``open`` - the double back-tick is a way to refer to reserved names)
Open is a function, so if you want to call it you need to give it an argument. You can treat it as a function value too and write, say, let f = dbConnection.Open
I also changed your naming to use camelCase for variables, which is the standard F# way

Map TRttiProperty to a class definition equivalent

I'm wondering if its possible to reference a class definition directly for purpose of using it in conjunction to RTTI (map a property to TRttiProperty, etc).
E.g.
I would like to use TMyClass.MyProperty as a TRttiProperty, without having to resolve it via a name/ string, this will keep my code and compiler integrity intact, as string variables may be misspelled, etc.
Thanks
Assuming which you want do something like this
P:=TRttiProperty(TMyClass.MyProperty);
or write a function like so
function GetPropertyInfo(P: reference to property):TRttiProperty;
This is not possible, to do this possible you will require which delphi has support to property references. So the only current way to access (reference) an class property is using his name via an string.

Regarding F# Object Oriented Programming

There's this dichotomy in the way we can create classes in f# which really bothers me. I can create classes using either an implicit format or an explicit one. But some of the features that I want are only available for use with the implicit format and some are only available for use with the explicit format.
For example:
I can't use let inline* (or let alone) inside an explicitly defined class.
The only way (that I know) to define immutable public fields (not properties*) inside an implicitly defined class is the val bla : bla syntax.
But there's a redundancy here. Since I'll end up with two copy of the same immutable data, one private, one public (because in the implicit mode the constructor parameters persist throughout the class existence)
(Not so relevant) The need to use attributes for method overloading and for field's defaults is rather off putting.
Is there anyway I can work around this?
*For performance reasons
EDIT: Turns out I'm wrong about both points (Thanks Ganesh Sittampalam & MichaelGG).
While I can't use let inline in both implicit & explicit class definition, I can use member inline just fine, which I assume does the same thing.
Apparently with the latest F# there's no longer any redundancy since any parameters not used in the class body are local to the constructor.
Will be gone in the next F# release.
This might not help, but you can make members inline. "member inline private" works fine.
For let inline, you can work around by moving it outside the class and explicitly passing any values you need from inside the scope of the class when calling it. Since it'll be inlined, there'll be no performance penalty for doing this.

Resources