I've just spent 20 hours in learning about the basics of Dart language, but when I find the # prefix in an open-source Dart program such as here, which I found that most programs use, I wonder what the # directive do in those programs...
For your information, the official documentation says the following:
Metadata
Use metadata to give additional information about your code. A metadata annotation begins with the character #, followed by either a reference to a compile-time constant (such as deprecated) or a call to a constant constructor.
Three annotations are available to all Dart code: #deprecated, #override, and #proxy. For examples of using #override and #proxy, see the section called “Extending a Class”. Here’s an example of using the #deprecated annotation:
However, what "additional information" does the # directive add to the code? If you create an instance by writing the following constructor
#todo('seth', 'make this do something')
, instead of the following constructor, which is the default:
todo('seth", 'make this do something')
, what is the benefit I can get from the first constructor?
I've got that using the built-in metadata such as #deprecated and #override can give me an advantage of being warned in running the app, but what can I get from the case on the custom #todo, or the aforementioned linked sample code over Github?
Annotations can be accessed through the dart:mirrors library. You can use custom annotations whenever you want to provide additional information about a class, method, etc. For instance #MirrorsUsed is used to provide the dart2js compiler with extra information to optimize the size of the generated JavaScript.
Annotations are generally more useful to framework or library authors than application authors. For instance, if you were creating a REST server framework in Dart, you could use annotations to turn methods into web resources. For example it might look something like the following (assuming you have created the #GET annotation):
#GET('/users/')
List<User> getUsers() {
// ...
}
You could then have your framework scan your code at server startup using mirrors to find all methods with the #GET annotation and bind the method to the URL specified in the annotation.
You can do some 'reasoning' about code.
You can query for fields/methods/classes/libraries/... that have a specific annotation.
You acquire those code parts using reflection. In Dart reflection is done by the 'dart:mirrors' package.
You can find an code example here: How to retrieve metadata in Dartlang?
An example where annotations are regularly used is for serialization or database persistence where you add metatdata to the class that can be used as configuration settings by the serialization/persistence framework to know how to process a field or method.
For example you add an #Entity() annotation to indicate that this class should be persisted.
On each field that should be persisted you add another annotation like #Column().
Many persistence frameworks generate the database table automatically from this metadata.
For this they need more information so you add a #Id() on the field that should be used as primary key and #Column(name: 'first_name', type: 'varchar', length: 32) to define parameters for the database table and columns.
This is just an example. The limit is you imagination.
Related
In my Java 8 Play 2.6 application I have this particular line in a MessageConsumer class that reads a "Rule" record in the DB and sends the JSON message (node) to a specific processor based on the type configured on the rule column. ProcessType is an enum of Sub Classes that all extend from a base (Super class) process.
Play.current().injector().instanceOf(ProcessType.getClass(matchingRule.getProcessType())).processMessage(node, matchingRule);
I'm having trouble figuring out how to refactor this and don't want to add the allowGlobalApplication = true config parameter if I can avoid it.
The most straightforward approach is to inject the Injector into the component that contains this call (the MessageConsumer). This can be done the same way as any other Play component.
You can also inject the Application instance, which would return the same thing as Play.current(). This could be useful if you need more information from the Application object, but if not, injecting the Injector directly would be preferable, as it would create less coupling between the MessageConsumer and other components.
This assumes that the MessageConsumer is created by DI itself. If not, please add more details to the question, including the context code.
I have some Dart classes in my project where I annotate some fields with Redstone Mapper's #Field() annotation.
How can I get all these classes at runtime?
I've seen the private Map _cache in redstone_mapper_factory... but it's private.
I'm aware of that I can use the Reflection package to scan these classes myself, however all of them are already being detected and stored by the Redstone mapper so I'd like to leverage that.
You can use dart:mirror to do that.
But I don't think it's possible to get that by redstone, you should probably ask on github, even do the change yourself if you want and do a pull request, it should not be difficult, it is just a getter on _cache.
https://github.com/redstone-dart/redstone_mapper
certainly I have not read something fundamental, and it seems very strange, but I wonder.
Suppose you use
#SharedPref
public interface SharedPreferencesInterface {
#DefaultBoolean(true)
boolean showDeviceName();
I have the IDE (idea) configured with Gradle, and I generated the SharedPreferencesInterface_ class that I can use in another class as
#Pref
SharedPreferencesInterface_ prefs;
But suppose someone now download the project, how can the use? Because the class where used SharedPreferencesInterface_ not compile because the class does not exist, and the class does not exist because compilation errors ...
How it's made? Surely there is a way ... configured to compile certain classes first?
Help is appreciated.
A greeting.
But suppose someone now download the project, how can the use? Because
the class where used SharedPreferencesInterface_ not compile because
the class does not exist, and the class does not exist because
compilation errors ...
This is the same situation when you compile a project in a full build (when no classes are generated yet). Actually Gradle always does a full build currently in Android projects. No configuration is needed at all in addition to the standard AndroidAnnotaions config.
Actually this works because the compiler does not fully compiles your class before passing it to annotations processing. It is clear it should not to, because the class may reference generated classes, which are only available after the processing. So first the compiler creates a model of the classes, only parses the structure of the them (fields, methods, return types, parameter types, etc), but not the implementations. Also it allows missing types even on fields. If it finds a missing type, it assigns to TypeKind.ERROR, but the name of the type is still available for the annotation processor. After the processor is done, it generates the missing class, so the kind of the class is no longer TypeKind.ERROR, and the compilation can succeed.
Is it possible to store additional data specific to the currently logged on user somehow?
Certainly! If you are not familiar with writing an extension, there are the VB.NET and C# guides on the subject.
You will need to extend the System.Security.Principal.IIdentity interface. As an example:
Declaration:
Imports System.Runtime.CompilerServices
Module Extensions
<Extension()>
Function GetMyCustomProperty(anIdentity As System.Security.Principal.IIdentity, myParameter As Integer) As Object
Return New Object()
End Function
End Module
Usage:
User.Identity.GetMyCustomProperty(4)
NOTES:
The C# code is a fair deal different so it's worth looking at the
guides on how extensions are implemented in general. Running this
code through a VB.NET => C# converter is not enough.
Extensions may only be methods. You may not program custom properties. This will likely mean implementing getter/setter methods if you want property-like behavior.
EDIT:
After seeing your comments, I assume you are doing this to provide a sort of crude functionality similar to a user profile. Consider using a profile provider in concert with any membership you are currently using if you'd like this functionality.
I am trying to make a taglib to represent an object (to read and display at the UI). When creating an object (save method in the controller), I see the domain class and association are created by the auto assignment of parameter
def Book = new Book(params)
It also maps complex types (for eg: joda time). I wonder about the naming convention necessary to facilitate this mapping. Out of curiosity, can someone also point where in the grails source code I could see how grails handles this mapping. I'm still learning Spring and probably this would be a good exercise.
Thanks,
Babu.
AFAIK the naming conventions are rather straightforward. If there's a field params.foo and the object you are binding to has a field foo, it will bind the value, assuming the type conversion works properly. If there's a params.bar.id set with an Long value and your object has a complex property of type Bar, it will lookup this instance and inject it.
If you need more control over the binding process, you might want to use bindData.
If you are interested into the details of the binding process, have a look at Java's PropertyEditor as this is what is being used in the background. I wrote a blog post on how to create and register PropertyEditors a while ago, maybe it helps you getting started with that stuff.