Skip to content

Allow customizing 'alias to bean' property not found behavior #2287

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Dec 17, 2019
Merged

Allow customizing 'alias to bean' property not found behavior #2287

merged 1 commit into from
Dec 17, 2019

Conversation

chris-peterson
Copy link
Contributor

@chris-peterson chris-peterson commented Dec 17, 2019

Scenario

A developer updates a stored procedure to return an additional column; this is generally expected to be a safe change.

The default behavior of AliasToBeanResultTransformer is to throw an exception when a value is observed but there is no field/property on the target instance to accept the value.

This change retains the existing behavior, but allows for specialization.

Here was the temporary workaround that I came up with which can be greatly simplified.

Before

        class PartialAliasToBeanResultTransformer<T> : AliasToBeanResultTransformer
        {
            readonly MethodInfo _setPropertyMethod;
            public PartialAliasToBeanResultTransformer() : base(typeof(T))
            {
                _setPropertyMethod = typeof(AliasToBeanResultTransformer).GetMethod("SetProperty", BindingFlags.NonPublic | BindingFlags.Instance);
            }

            public override object TransformTuple(object[] tuple, string[] aliases)
            {
                var result = ResultClass.IsClass
                    ? BeanConstructor.Invoke(null)
                    : Activator.CreateInstance(ResultClass, true);

                for (int i = 0; i < aliases.Length; i++)
                {
                    SetPropertyHelper(aliases[i], tuple[i], result);
                }

                return result;
            }

            static Type ResultClass => typeof(T);
            static ConstructorInfo BeanConstructor => ResultClass
                .GetConstructor(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance,
                    null,
                    Type.EmptyTypes,
                    null);

            void SetPropertyHelper(string alias, object value, object resultObj)
            {
                try
                {
                    _setPropertyMethod.Invoke(this, new object[] {alias, value, resultObj});
                }
                catch (TargetInvocationException ex)
                {
                    if (!(ex.InnerException is PropertyNotFoundException))
                    {
                        throw;
                    }
                }
            }
        }

After

        class PartialAliasToBeanResultTransformer<T> : AliasToBeanResultTransformer
        {
            protected override void OnPropertyNotFound(string propertyName)
            {
            }
        }

hazzik
hazzik previously approved these changes Dec 17, 2019
There are cases when you might not want to throw an exception
@chris-peterson
Copy link
Contributor Author

@hazzik -- thanks for the review (and fixing my missing void mistake). I've updated from upstream and rebased so the change history will be tidy.

@hazzik hazzik merged commit 92133f0 into nhibernate:master Dec 17, 2019
@hazzik hazzik added this to the 5.3 milestone Dec 17, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants