Skip to content
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

IgnoreProperty does not ignore overridden properties in sub-classes #109

Open
chilversc opened this issue Nov 11, 2011 · 3 comments
Open
Labels

Comments

@chilversc
Copy link

mapping.IgnoreProperty (x => x.IsOverriden) does not ignore properties that are overriden in sub-classes.
Further more, it cannot ignore properties that are overriden in sub-classes.

Eg

    public class ItemBase { public virtual bool IsOverriden { get { return false; } } }
    public class Item : ItemBase { public override bool IsOverriden { get { return true; } } }

This partially works, it will ignore ItemBase.IsOverriden but not Item.IsOverriden

    public void Override (AutoMapping<ItemBase> mapping) {
        mapping.IgnoreProperty (x => x.IsOverriden);
    }

This does not work, Item.IsOverriden will not be ignored.

    public void Override (AutoMapping<Item> mapping) {
        // This does not work, it will not ignore Item.IsOverriden
        mapping.IgnoreProperty (x => x.IsOverriden);
    }

As a work around the following does work:

    public void Override (AutoMapping<Item> mapping) {
        mapping.IgnoreProperty (Reveal.Member<Item> ("IsOverriden"));
    }

The following example reproduces the error with FNH 1.3.0.717 and earlier: https://gist.github.com/1358583

// uses NHibernate 3.2.0.4000
// uses FluentNHibernate 1.3.0.717

namespace ConsoleApplication1
{
    using System;
    using System.IO;
    using FluentNHibernate;
    using FluentNHibernate.Automapping;
    using FluentNHibernate.Automapping.Alterations;
    using FluentNHibernate.Cfg;
    using FluentNHibernate.Cfg.Db;

    public class Program
    {
        public static void Main()
        {
            var cfg = new AutoMappingConfiguration ();
            var mapping = AutoMap
                .AssemblyOf<AutoMappingConfiguration> (cfg)
                .UseOverridesFromAssemblyOf<AutoMappingConfiguration> ()
                .Conventions.AddFromAssemblyOf<AutoMappingConfiguration> ();

            using (var file = File.CreateText ("mapping.xml"))
                Fluently.Configure ()
                    .Database (SQLiteConfiguration.Standard.InMemory)
                    .ProxyFactoryFactory<NHibernate.Bytecode.DefaultProxyFactoryFactory> ()
                    .Mappings (m => m.AutoMappings.Add (mapping).ExportTo (file))
                    .BuildConfiguration ();
        }
    }

    public class AutoMappingConfiguration : DefaultAutomappingConfiguration
    {
        public override bool ShouldMap(Type type)
        {
            return type == typeof (ItemBase) || type == typeof (Item);
        }
    }

    public class ItemBaseOverride : IAutoMappingOverride<ItemBase>
    {
        public void Override (AutoMapping<ItemBase> mapping)
        {
            mapping.IgnoreProperty (x => x.IsOverriden);
        }
    }

    public class ItemOverride : IAutoMappingOverride<Item>
    {
        public void Override (AutoMapping<Item> mapping)
        {
            // Fails:
            mapping.IgnoreProperty (x => x.IsOverriden);

            // Works:
            //mapping.IgnoreProperty (Reveal.Member<Item> ("IsOverriden"));
        }
    }

    public class ItemBase
    {
        public long Id { get; set; }
        public string Name { get; set; }

        public virtual bool IsOverriden
        {
            get { return false; }
        }
    }

    public class Item : ItemBase
    {
        public override bool IsOverriden
        {
            get { return true; }
        }
    }
}

Example Result (cleaned up a little)

<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2">
  <class xmlns="urn:nhibernate-mapping-2.2" name="ConsoleApplication1.ItemBase, ConsoleApplication1" table="`ItemBase`">
    <id name="Id">
      <generator class="identity" />
    </id>
    <property name="Name" />
    <joined-subclass name="ConsoleApplication1.Item, ConsoleApplication1">
      <key>
        <column name="ItemBase_id" />
      </key>
      <property access="property" name="IsOverriden" />
    </joined-subclass>
  </class>
</hibernate-mapping>
@chilversc
Copy link
Author

Ideally I think auto-mapping should ignore properties in sub-classes that are already mapped by a super-class rather than mapping the same property twice.

Cases

  1. super-class is not mapped, thus property is not mapped, sub-class must define the property.
  2. super-class is mapped, thus the property is mapped, sub-class must not define the property.
  3. super-class is mapped but property was ignored, thus property is not mapped, sub-class must define the property.
  4. super-class is mapped but property was ignored for all sub-classes, thus property is not mapped, sub-class must not define the property.

3 could be optional if 4 is always assumed. I.E. ignores are always inherited, though this would be a breaking change.
4 would require adding an extra ignore method to AutoMapping<T>, e.g. mapping.IgnorePropertyForAllSubClasses (x => x.IsOverriden)

It might also be worth while looking at how inheritance as a whole is handled rather than just ignoring properties as a similar problem occurs when declaring a super-class' abstract property as Access.ReadOnly(), you then have to ignore that property from each of the sub-classes.

@mattwang75
Copy link

Fwiw, we have the exact problem. We want our overridden property in base class and subclasses ignored. While it ignores in base class, it doesn't in subclasses.

@chester89
Copy link
Collaborator

I understand the problem, but I'm not sure how to approach this. Also, breaking change isn't a good idea for a minor release. If only @jagregory can give some advice

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants