Extending / Modifying NHibernate Classes at Run Time

Sorry if there is already an answer to the point, but I did not find it. I use NH3, and I have a use case when I want to add Set to any object whose class implements a specific interface. I have a configuration builder class, so I can make these changes before creating a factory session.

Given the example below:

public class Person : IHasExtraItems { public Person() { this.ExtraItems = new HashSet<ExtraItem>(); } public virtual Guid Id { get; set; } public virtual string Name { get; set; } public virtual DateTime Birthdate { get; set; } public virtual ICollection<ExtraItem> ExtraItems { get; protected set; } } public class ExtraItem { public virtual Guid Id { get; set; } } 

And this example:

  <class name="Person"> <id name="Id"> <generator class="guid"/> </id> <property name="Name"/> <property name="Birthdate"/> <set name="Extra" table="PersonExtraItems" cascade="all"> <key column="PersonId"/> <many-to-many column="ExtraItemId" class="ExtraItem" unique="true" /> </set> </class> 

Since I want to be able to apply this functionality to many classes transparently - just by implementing the interface - I don't want to put "ExtraItem" in the display. Instead, I want to add it at runtime. So, if I remove the property from the xml mapping, how can I add this at runtime?

This is the exact type of change I'm trying to make: http://ayende.com/Blog/archive/2008/05/01/Dynamic-Mapping-with-NHibernate.aspx

But it does not display many sets, and my weak brain was unable to decipher the representation of memory mapping in memory, which nhibernate uses to create the effect. This is the closest I came based on an attempt to get the properties visible in the debugger to match

 foreach (var cls in cfg.ClassMappings) { if (typeof(IHasExtraItems).IsAssignableFrom(cls.MappedClass)) { NHibernate.Mapping.Property property = new NHibernate.Mapping.Property(); NHibernate.Mapping.Set value = new NHibernate.Mapping.Set(cls); value.Role = cls.EntityName + ".ExtraItems"; value.IsGeneric = true; var table = new Table(); table.Name = cls.MappedClass.Name + "ExtraItems"; value.CollectionTable = table; value.GenericArguments = new Type[] { typeof(ExtraItem) }; value.IsOptimisticLocked = true; value.IsLazy = true; mappings.AddCollection(value); property.Value = value; property.Name = "ExtraItems"; property.PersistentClass = cls; property.Cascade = "all"; cls.AddProperty(property); } } 

In the test, this leads to a runtime error, because the key is null, however, the version with the XML mapping works and looks more or less identical when making changes.

Bonus points . I want many-to-many to be special, because I need a joined table. This allows me to map the entity to expanding data with true foreign keys for performance. ExtraItems should really be a value type, not a true entity, but I couldn't figure out how to map this, even in XML.

Reward Points, Part 2: Can I do this with confORM? I do not want to switch all existing mappings to confORM, and I could not find an example of mixing confORM with regular XML mappings without changing the existing mappings. Fluent will be another option, but I am using NH3 and I don't think Fluent supports this.

Thanks in advance!

EDIT I am sure my problem is that I do not define the elements of the set. However, I cannot figure out how to correctly define the elements of a set.

+4
source share
1 answer

NH3 has built-in features, so you can use it (s), and if you are fluent, you can very easily do this with the help of a convention. You mentioned that in the section of your bonus points, maybe you should give it a different look?

+1
source

Source: https://habr.com/ru/post/1338374/


All Articles