Last but not least is the enigmatic DeepCopy... reading some of the drudged
up old blogs, different folks interpretations over IUserType, take aways
are all over the map. Best I can figure, and from debugging, and since you
are not given 'object owner', either...
One has to disassembly the value. Whereas assembling a value you are given
the owner. So I again take away the reasonable conclusion that Assembly and
Disassembly are central.
public virtual object DeepCopy(object value) => value switch
{
null => null,
R r => Disassemble(r),
_ => throw new InvalidOperationException($"Unable to deep copy value
type '{value.GetType()}'.")
};
On Tuesday, June 10, 2025 at 2:53:08 PM UTC-4 Michael W Powell wrote:
> Extending that thought a bit, from what I could determine Equals is a bit
> nuanced as well. First argument x appears to be cached or disassembled,
> whereas it would seem second argument y appears to be assembled version of
> the same.
>
> protected virtual bool Equals(P x, P y) => x is IEquatable<P> xe && y is
> IEquatable<P> ye && xe.Equals(ye);
>
> public new virtual bool Equals(object x, object y)
> {
> object Normalize(object value) => value switch
>
> {
> null => null,
> R r => Disassemble(r),
> P p => p,
> _ => throw new InvalidOperationException($"Unsupported equality
> value type '{value.GetType()}'.")
> };
>
> x = Normalize(x);
> y = Normalize(y);
>
> return (x is null && y is null)
> || ReferenceEquals(x, y)
> || (x is P xp && y is P yp && Equals(xp, yp))
> //|| (x is R xr && y is R yr && Equals(xr, yr))
> ;
> }
>
> It's unlikely probably would see an R clause (returned class), as
> contrasted with the P clause (primitive class).
>
> The Normalize local function is also geared at any rate along the same
> lines to compare vis-a-vis the primitive type.
>
> Then Equals(P, P), after having ruled out null and reference equality,
> base implementation whether P is IEquatable<P> can just do it then.
>
> Allowing for authors to extend as needed.
>
> On Tuesday, June 10, 2025 at 1:13:17 PM UTC-4 Michael W Powell wrote:
>
>> Hello,
>>
>> Double checking my work implementing IUserType. Implementing to
>> facilitate mapping types to postgres Npgsql. Specifically in one case to
>> JSON/JSONB column types, facilitated by either string, then to
>> Newtonsoft.Json.Linq JObject or JArray, both JContainer, depending on the
>> use case.
>>
>> Best I can figure, Assemble and Disassemble are somewhat core and central
>> of such an implementation. Around the NullSafeGet and Set, for instance.
>> Almost to a point where it might be worth providing a generic serialization
>> implementation, interface, etc, but starting from here:
>>
>> public virtual object NullSafeGet(DbDataReader rs, string[] names,
>> ISessionImplementor session, object owner)
>> {
>> this.VerifyNullSafeNames(names: names);
>>
>> var name = names[0];
>> var ordinal = rs.GetOrdinal(name);
>> var value = rs[ordinal];
>> return value switch
>> {
>> null => null,
>> P p => Assemble(p, owner),
>> _ => throw new InvalidOperationException($"Unable to get null
>> safe value, names: [{string.Join(", ", names)}].")
>> };
>> }
>>
>> public void NullSafeSet(DbCommand cmd, object value, int index,
>> ISessionImplementor session)
>> {
>> // We expect there to be an parameter of this type.
>> if (cmd.Parameters.TryGetValue<NpgsqlParameter>(index, out var arg))
>> {
>> // Parameter Value may be either null, of types R or P, otherwise
>> throw.
>> arg.Value = value switch
>> {
>> null => null,
>> R r => Disassemble(r),
>> P p => p,
>> _ => throw new InvalidOperationException($"Unable to set null
>> safe value type '{value.GetType()}' index {index}.")
>> };
>>
>> // Indeed return here since we do not want to throw the default
>> parameter ex.
>> return;
>> }
>>
>> throw new InvalidOperationException($"Unable to set null safe
>> parameter value index {index}.");
>> }
>>
>> Here I verify names apart from the implementation. Also I look up the
>> postgres Npgsql parameter in this instance.
>>
>> But the core of the approach, I think, are Assemble and Disassemble, from
>> what I can gather. Everything revolves around that, including DeepCopy.
>>
>> Mostly everything else is pretty boilerplate, in my estimation, so any
>> specialization can focus on the A/D overrides. Sometimes perhaps also the
>> Equals.
>>
>> public abstract class NpgsqlJsonCustomTypeBase<P, R> : IUserType
>> {
>> // ...
>> }
>>
>> Have verified through mappings and to a test project, seems to satisfy
>> things.
>>
>> Posting here in case I am missing something, perhaps there are gaps I am
>> unaware of.
>>
>> Appreciate the feedback.
>>
>> Best regards,
>>
>> Michael W. Powell
>>
>
--
You received this message because you are subscribed to the Google Groups
"Fluent NHibernate" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To view this discussion visit
https://groups.google.com/d/msgid/fluent-nhibernate/034d0171-2512-477e-a9df-26e1680bc803n%40googlegroups.com.