With.Fody
With.Fody copied to clipboard
Relax the type checking
Hi. I started using this the other day and must say it makes working with my DDD aggregate state objects much nicer. My only gripe is the initial checking between properties and the constructors available.
It feels too strict limiting the types to matching types. For example, I expose an ImmutableArray<T>
but my constructor takes IEnumerable<T>
, as this is the only contract required during construction. These constructors are therefore not found by the GetValidConstructor
method. I believe the With
method should type-match the property, as it's meant to mimic the F# style, however it doesn't need to be too prescriptive on the constructors used.
One that I like is to stipulate that the type needs to have a constructor that has arguments for all properties and the parameters should share the property name, no more. Type issues can be left to the developer. We could do type checking, but I would suggest checking that the property is assignable to the constructor argument (as the property might be derived from the argument and the constructor translates it) or that the argument is assignable to the property (the property might expose an IEnumerable<T>
where the constructor takes a T[]
). The With
should match the constructor.
What are your thoughts on this?
Hi. Great to hear that you find it useful!
I think the idea to relax the check to IsAssignableFrom
makes sense. Fancy making a PR?
Yeah happy to. I'll go with the approach of checking assignable in both directions (so that it doesn't depart too much from what's sensible).
Another use case I will cover is Nullable<T>
, which has just stung me. I have a DateTime?
on my state object, but due to the domain it is not valid to set null, only a real value, from public code.
Evidently type walking in Cecil is odd. I can do sub-class or interface checks, however arrays start to go a little funny (I guess because of all the special compiler-level support they get). This could degenerate into a complete mess of code to handle edge cases.
I then tried to fall back onto reflection, but this gets a little messy trying to load types in the correct assemblies.
Edging towards just doing it by name and letting the runtime complain if developers want to do stupid things lol