Closed focustense closed 2 weeks ago
Committed a working implementation for this. Don't yet know how well it works, but the existing types give a decent amount of stress testing already with default parameters, nullable value types, etc., so it should cover a wide range of cases.
Probably needs a quick doc update on the type conversions so I won't close this until that's added.
Was getting ready to close this, and then read over the notes again and realized that I completely forgot about collections, so this could drag on for quite a while longer, unfortunately.
Still, it's in a pretty good state as most (maybe all?) of the types that would actually benefit from this conversion don't use collections anyway: Sprite
, Edges
, Bounds
, etc.
(Edit: Was clearly suffering from lack of sleep. Collection conversions have nothing to do with duck types; they should operate the same way as Nullable<T>
conversions. If the basic "form" of collection - list, dictionary, etc. - is convertible, and the element type is convertible through any means, then the collection itself is convertible.)
A lot of the design in the Framework and StarML is oriented around Pintail and its requirements, but it recently occurred to me that after data binding has occurred, Pintail is entirely irrelevant; that is, view bindings have direct access to the bound context and so Pintail wouldn't help with "proxying" at that point even if the types were interfaces.
So really, it's up to StardewUI to decide whether or not to support this fuzzy type conversion. There's a case to be made that it should. For example, suppose the client defines:
or even
These aren't assignment-compatible with
Sprite
, but their properties are assignment-compatible with all the required properties ofSprite
. Having some form of duck typing is really not a far cry from what the Framework is already doing with property assignments and conversions.A possible specification would go as follows:
struct
types are fine, just not primitives.Additionally, if the only matching constructor (or the only constructor at all) is a default parameterless constructor, and there aren't any properties on the source type matching properties on the destination type, then either don't allow the conversion, or log a prominent warning (one time) that the conversion is meaningless and therefore probably wrong.
This might need to handle fields on the source type, too. While I'm not crazy about it due to the performance issues, I expect it's just going to be a thing that comes up. (See rationale in #15).
This specification heavily favors
record
types, in which ctor args are always the same as property names, and that's intended. It can still be made to work with other classes, though, by using case-insensitive comparisons or case transformations as mentioned earlier.Anticipated challenges include:
Side note: while the practice should be heavily discouraged, this also solves the problem with devs importing the Core Library as a Shared Project and trying to use those types; since they are in fact the same logical types, they should always be duck-type compatible.