When trying to access a Firestore database using Kotlin, the error quoted in the title is thrown. The fields of my model class exactly match the Firestore documents I'm trying to access. Why does Android Studio say there is no setter/field?
There is another field in the same class, which apparently works correctly, no error has been thrown. Even their type is the same, both are Boolean. The only difference is in their names, isCreator and admin (the working one).
The problem was with the properties' names. When a property's name starts with "is", one has to explicitly annotate the property's getter the following way:
#get:PropertyName("isCreator")
val isCreator: Boolean
If your property is mutable (aka var), you also have to annotate the setter;
#get:PropertyName("isCreator")
#set:PropertyName("isCreator")
var isCreator: Boolean
Related
I actually solved my problem before posting, but I wonder if there are any better solutions?
Also if there is somewhere where there is a way to use list as-is?
I am writing a simple get endpoint if F# which needs to accept a list of strings as an argument.
I take that list as the input to a query that runs as expected, I am not worried about that part.
The problem I am facing is as follows (minimal implmenetation):
When I define the endpoint as:
[<HttpGet>]
member _.Get() =
processStrings [ "test"; "test2" ]
it returns as expected.
When I change it to:
[<HttpGet>]
member _.Get([<FromQuery>] stringList: string list) = processStrings stringList
I get an error:
InvalidOperationException: Could not create an instance of type 'Microsoft.FSharp.Collections.FSharpList`1[[System.String, System.Private.CoreLib, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]]'. Model bound complex types must not be abstract or value types and must have a parameterless constructor. Record types must have a single primary constructor. Alternatively, give the 'stringList' parameter a non-null default value.
Which doesn't make much sense to me, as I am using a list of strings, which in C# at least defaults to an empty list.
So I assume this comes down to how C# and F# interpret these signatures, but I am not sure how to resolve it.
I tried this signature and received the same error as above....
member _.Get( [<Optional; DefaultParameterValue([||]); FromQuery>] stringList: string list) = processStrings stringList
In the end using the following did solve the problem.
member _.Get( [<Optional; DefaultParameterValue([||]); FromQuery>] stringList: string seq) = processStrings stringList
I assume it was solved because seq is just IEnumerable, and then presumable list isn't just List from C# (mutable vs immutable). But is there a way to use an F# list in [FromQuery] parameters? Would [FromBody] have just worked? (No is the tested answer) Is there a way to add a type provider for an endpoint like this?
Is there something else I am missing here? Mine works now, but I am curious to the implications of the above.
I have not tested this, but I would assume that ASP.NET does not support F# lists as arguments. I would guess that taking the argument as an array would be much more likely to work:
[<HttpGet>]
member _.Get([<FromQuery>] stringList: string[]) =
processStrings (List.ofArray stringList)
I am using bean validation to validate my entity,
it works fine according to different locales and it shows region-specific error messages, but I want to internationalize a field 'ContactNo' according to the region like my error messages #NotBlank(message="{contactNo.size}").
So how to achieve
#Pattern(regexp="(^$|[0-9]{10})")
private String contactNo;`
where the regexp value changes according to the region?
The the value for the regexp attribute has to be constant i.e. it needs to be available at compile time. So, either it needs to be a string literal as you do now or externalized into a static final variable.
I guess what you need has to be implemented in a custom Bean Validation constraint.
I am trying to make a replacement VB6 class for the Scripting.Dictionary class from SCRRUN.DLL. Scripting.Dictionary has (among other things) a "Keys" method that returns an array of keys, and a read/write "Item" property that returns the item associated with a key. I am confused about this, because both of them seem to be defaults for the class. That is:
For Each X In MyDict
Is equivalent to:
For Each X In MyDict.Keys
Which to me implies that "Keys" is the default operation for the class, but:
MyDict("MyKey") = "MyValue"
MsgBox MyDict("MyKey")
Is equivalent to:
MyDict.Item("MyKey") = "MyValue"
MsgBox MyDict.Item("MyKey")
Which to me implies that "Item" is the default operation for the class.
I've never before created a VB6 class that had a default operation, so upon realizing this, I thought perhaps I could define multiple default operations as long as they all have different signatures, which they do: Keys is nullary, the Item getter takes a Variant, and the Item setter takes two Variants. But this doesn't seem to be allowed: When I use "Tools/Procedure Attributes" to set the Keys function to be the default, and then I use it to set the Item property to be the default, the IDE complains that a default has already been set.
So I think I'm misunderstanding something fundamental here. What is going on in the Scripting.Dictionary object that makes it able to act as if "Keys" is the default in some contexts, but as if "Item" is the default in others? And whatever it is, can I accomplish the same thing in VB6?
OK, answering my own question: I haven't tried this yet, but I gather that "Item" should be made the default, and that I should add an entirely new function called "NewEnum" that looks something like the following (slightly modified from an example in Francesco Balena's "Programming Microsoft Visual Basic 6.0" book):
Public Function NewEnum() As IUnknown
Set NewEnum = m_Keys.[_NewEnum]
End Function
(where "m_Keys" is a Collection containing the keys), and then use Tools/Procedure Attributes to hide NewEnum and to set its ProcID to -4.
What you are observing is the difference between the default member and a collection enumerator. A COM object (including VB6 classes) can have both.
You can identify the default property of a class by looking in the Object Browser for the tiny blue globe or the words "default member of" in the description (see Contents of the Object Browser). The Object Browser will not identify an enumerator method, but if you look at the class's interface definition using OLE View or TypeLib Browser (free but registration required) it's DispId will be 0xfffffffc or -4.
In your own class, you can mark the default property by setting the Procedure ID to "(default)" in the Procedure Attributes dialog (see Making a Property or Method the Default). You already listed the steps for setting up the collection enumerator in your own answer, but you can find this listed as well in the Programmer's Guide topic Creating Your Own Collection Class: The House of Bricks.
Scripting.Dictionary has a dirty secret:
It does not handle enumeration at all, it returns big ugly Variant arrays and your For Each loops iterate over those.
This is one of the reasons why a Dictionary can actually be far less efficient than a standard VB6 Collection.
Given a JSON string of the form {"$type":"MyType, MyAssembly","seed":0"}, why can't JsonConvert.DeserializeObject utilize the JsonConverter associated with "MyType"?
I've tried decorating the MyType class with a [JsonConverter(typeof(MyType))] attribute. Doesn't work. The custom JsonConverter's ReadJson method is never called.
I've tried adding the custom converter to the serializer's settings Converters collection and made sure the CanConvert method returns true for 'MyType' and the CanRead method returns true. Doesn't work. Neither the converter's CanConvert nor its ReadJson method is ever called.
The DeserializeObject method needs to be able to deserialize a JSON string containing an object whose type is unknown at compile time, but whose type is embedded in the JSON object via the special "$type" member. So don't suggest using DeserializeObject<T> or point out that it works for members, whose type is identified in the contract before hand.
FYI, this problem generalizes to cases where the deserialization needs to identify the object type solely from the embedded "$type" member, so for example, it also fails to resolve a converter if the JSON object is in an untyped JSON array, not just at the top-level.
Basically, an object cannot survive a round trip through the serialization/deserialization process, because although the WriteJson method will be called for the Converter when SerializeObject is called, when you subsequently pass the JSON string to DeserializeObject, it fails to call the converter's ReadJson method, and instead constructs an new instance and uses the basic member population routines.
I am writing a small code generator which would read into an edmx file and create business objects on the base of a template. I am using reflection to spit out the type names.
The problem is when I encounter a property (PropertyInfo) of type Entity Reference, (basically an entity property if there is a referential integrity), the PropertyInfo.PropertyType.Name comes as "EntityReference`1" which is not recognized by the compiler.
PropertyInfo.PropertyType.FullName gives "System.Data.Objects.DataClasses.EntityReference`1[[BusinessObjectGenerator.Models.BE_Additional_Info, BusinessObjectGenerator, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]]", which is also not recognized by the C# compiler.
Now I faced the same problem with the Nullable types. And I found the static method Nullable.GetUnderlyingType(type) which solved the issue. How do I get the name of type of a property that is an entity type, a name that the C# compiler recognizes?
Generic types contain ` in their Name. To get the C# readable name of the type, you will need to first check if it is a generic type using Type.IsGenericType. If it is a generic type, then you can use Type.GetGenericArguments() to get the list of type arguments to the generic type. By getting their names, you can put together the generic type name like. For example, if the type is
Dictionary<int, string>
Then, the type name would actually be Dictionary`2. Using GetGenericArguments would return an array with two types (int, and string). From these you can generate the composite name.
Note: Each of the types returned from GetGenericArguments() may itself be a generic type, so you should write this as a recursive algorithm.