I think what I've been saying may have been interpreted as being more negative or hostile than I intended it to be. My basic point was, there isn't a bug because you aren't using a "feature" of FNH. I'm happy for this to become a proper supported way of overriding automappings, but for me to be expected to support it I have to actually write coverage for it. Until I do that, it's unofficial.
As for my stance on actually using it, as long as it's explained that they are overrides (and as Steve said, with a decent naming convention) there's nothing wrong with inheriting from AutoMap<T>. I'm all for SoC. Billy: do you prefer your new way of writing the overrides, or would you prefer to just inherit from AutoMap? Is this new way just to avoid the bug? What I'm saying is: say the word and I'll make this an official feature; then I won't moan about not supporting an unofficial feature. On Mon, Feb 9, 2009 at 7:29 PM, Billy <wmccaffe...@gmail.com> wrote: > > Here's the final approach that I took to organize my overrides: > > 1) Add an override interface to your application as follows: > > using FluentNHibernate.AutoMap; > > namespace SharpArch.Data.NHibernate.FluentNHibernate > { > /// <summary> > /// Used by <see cref="AutoPersistenceModelExtensions" /> to add > auto mapping overrides > /// to <see cref="AutoPersistenceModel" /> > /// </summary> > public interface IAutoPeristenceModelConventionOverride > { > AutoPersistenceModel Override(AutoPersistenceModel model); > } > } > > 2) Create an extension method, as follows, to look for every class > which implements IAutoPeristenceModelConventionOverride, in a > particular assembly, and apply the override to AutoPersistenceModel: > > using FluentNHibernate.AutoMap; > using System.Reflection; > using System; > using SharpArch.Core; > > namespace SharpArch.Data.NHibernate.FluentNHibernate > { > /// <summary> > /// Provides a means to override <see cref="AutoPersistenceModel" / > > conventions with classes > /// that implement <see > cref="IAutoPeristenceModelConventionOverride" />. > /// </summary> > public static class AutoPersistenceModelExtensions > { > public static AutoPersistenceModel > MapConventionOverridesFromAssemblyOf<TOverride>( > this AutoPersistenceModel autoPersistenceModel) where > TOverride : IAutoPeristenceModelConventionOverride { > > Assembly assemblyToPullConventionOverridesFrom = typeof > (TOverride).Assembly; > > foreach (Type type in > assemblyToPullConventionOverridesFrom.GetTypes()) { > if (typeof > (IAutoPeristenceModelConventionOverride).IsAssignableFrom(type)) { > IAutoPeristenceModelConventionOverride instance = > Activator.CreateInstance(type) as > IAutoPeristenceModelConventionOverride; > > if (instance != null) > instance.Override(autoPersistenceModel); > } > } > > return autoPersistenceModel; > } > } > } > > 3) Create a class for each entity that requires a convention override; > for example: > > using FluentNHibernate.AutoMap; > using Northwind.Core; > using SharpArch.Data.NHibernate.FluentNHibernate; > > namespace Northwind.Data.NHibernateMappings > { > public class CustomerMap : IAutoPeristenceModelConventionOverride > { > public AutoPersistenceModel Override(AutoPersistenceModel > model) { > return model.ForTypesThatDeriveFrom<Customer>(map => { > map.SetAttribute("lazy", "false"); > }); > } > } > } > > 4) Include a call to the extension method when setting up the > AutoPersistenceModel; e.g., > > AutoPersistenceModel mappings = AutoPersistenceModel > .MapEntitiesFromAssemblyOf<Customer>() > ... > .WithConvention(GetConventions) > .MapConventionOverridesFromAssemblyOf<CustomerMap>(); > > I'll be including this approach in the next release of S#arp > Architecture which leverages Fluent NHibernate. Hope this helps! > > Billy McCafferty > > > On Feb 9, 9:03 am, Steven Harman <stevehar...@gmail.com> wrote: > > Being one of the folks currently using the AutoPersistenceModel in an > > unconventional (or rather, just unexpected) manner, I suppose I should > speak > > up in favor of allowing, and suggesting, that class-specific convention > > overrides be split out into their own auto mappings files. I'm on board > > w/Andy - this approach keeps things more granular, better seperated, and > > easier to grok when you have a large number of mappings. > > > > That said, I also see James concern that it might not be obvious that > these > > small one-off maps are actually overriding some other auto mapping, setup > > elsewhere. However, I think some smart naming conventions, namespacing, > and > > a little bit of education could go a long way toward eliminating that > > concern. But then, that's just my opinion. > > > > Perhaps talking about the various ways folks are using FNH mappings (both > > auto and manual), and the lessons we're learning, would be a good topic > for > > a VAN Meeting? > > > > -steve > > > > //---- 90% of being smart is knowing what you're dumb at ----// > http://stevenharman.net/ > > > > On Mon, Feb 9, 2009 at 9:44 AM, AndyStewart <andrewnstew...@gmail.com > >wrote: > > > > > > > > > Hi James > > > > > I've not read the whole thread, so forgive me if I'm going in the > > > wrong direction. However let me shed some light on this, > > > looks like some users of the library are inheriting from AutoMap and > > > using the model.addMappingsFromAssembly( ); method. > > > This is in-fact the very first way I wrote automappings, until Chad > > > showed me the light to the fluent method. However if > > > your doing alot of custom mappins then loading in via seperate classes > > > is a lot cleaner than the 80 lins of fluent code > > > I have in one of my projects (yuk). > > > > > Hope you this puts you in the picture as how this has come about. > > > > > Andy > > > > > On Feb 9, 10:33 am, James Gregory <jagregory....@gmail.com> wrote: > > > > Billy, it's important to note that I never said you shouldn't be > deriving > > > > from AutoMap<T>. If that works for you (or did...) then great. My > point > > > is > > > > that this style of modeling has evolved without my knowledge, which > is > > > > interesting and concerning at the same time; if it's a good thing > then I > > > > have no issue with it, but I can't be seen to endorse it without > > > > understanding the implications of it's use beforehand. > > > > For starters, we have no tests covering this code; which leads us to > > > > situations like this where I manage to break it for people without > ever > > > > knowing. We have no examples promoting this style (unless somebody's > > > written > > > > some I wasn't aware of), and as a result we have no way of supporting > > > this > > > > from a guidance perspective. > > > > > > My final disagreement with this is that I don't actually like the way > it > > > > feels. It looks like a ClassMap, smells like a ClassMap, but is an > > > AutoMap. > > > > You look at it and, unless you already know that it's an AutoMap, > think > > > > "where are all the other mappings?" However, that could just be me > > > because > > > > I'd not used it in this manner. > > > > > > All that being said, I can definitely see the merit in separating the > > > > overrides into their own classes. People obviously like doing > overrides > > > in > > > > the manner that #arch does them, so presuming I can get the code > under > > > test > > > > (and fix the bug), I have no issue with people proceeding. > > > > > > I've got some time tomorrow working on FNH, so I'll take a look at > this > > > > then. > > > > > > On Mon, Feb 9, 2009 at 3:16 AM, Billy <wmccaffe...@gmail.com> wrote: > > > > > > > I was also inheriting from AutoMap and ran into the same exception > > > > > with recent updates. The workaround that I've put in place for > this > > > > > issue for keeping overrides well organized is described at > > > > > > > > http://groups.google.com/group/sharp-architecture/msg/c74d493fc74ed98. > > > .. > > > > > . > > > > > Although it's within the context of S#arp Architecture, it could be > > > > > reused in any project. > > > > > > > Billy McCafferty > > > > > > > On Feb 3, 12:13 pm, Jimit <jimitndi...@gmail.com> wrote: > > > > > > The method MergeWithAutoMapsFromAssembly<T>() seemed to suggest > the > > > > > > style I used - that is, subclassing AutoMap<T> in an assembly. It > did > > > > > > discover my automaps fine, but then failed with the error > described. > > > > > > My domain has some very deep hierarchies and the fluent > configuration > > > > > > (using ForTypesThatDeriveFrom<T>) was getting rather wordy so I > > > > > > seperated them into individual subclasses of AutoMap<T> and > merged > > > > > > them into my AutoPersistenceModel using > > > > > > MergeWithAutoMapsFromAssembly<T>(). It seemed to work fine, until > it > > > > > > didn't. :) I think subclassing AutoMap<T> should be supported, > if > > > > > > nothing else than for consistency with ClassMap<T> for > non-automapped > > > > > > entities. > > > > > > > > Speaking of ForTypesThatDeriveFrom<T>, I think a non-generic > overload > > > > > > might come in handy. One use case (that's got me stumped at the > > > moment > > > > > > - having to use reflection) is setting conventions for the open > form > > > > > > of a generic base type, e.g EntityBase<,>. In my particular case, > I > > > > > > want to ignore certain properties in EntityBase<TEntity,TId> but > > > don't > > > > > > want to have to tell the Automapper to ignore it for each > individual > > > > > > TEntity. Any suggestions? > > > > > > On a side note, you mentioned a check-in adding support for > mapping > > > > > > generic base classes > > > > > > > > On Feb 3, 4:32 pm, James Gregory <jagregory....@gmail.com> > wrote: > > > > > > > > > Hi, > > > > > > > You seem to be correct in your analysis. The reason this is > > > happening > > > > > is > > > > > > > because it was never intended that people would subclass > > > AutoMap<T>; > > > > > > > alterations to classes are supposed to be done in the > > > > > > > ForTypesThatDeriveFrom<T> call on the automapper, rather than > in a > > > > > subclass. > > > > > > > > > I realise this is probably quite annoying, but I'm not willing > to > > > > > endorse > > > > > > > this style of automapping until I've done some investigation > into > > > it's > > > > > > > implications. For the time being, I'd recommend either altering > > > your > > > > > code to > > > > > > > use the recommended ForTypesThatDeriveFrom call, or altering > the > > > code > > > > > > > yourself. > > > > > > > > > I will make a note to review this style to see if it's > something we > > > > > should > > > > > > > officially support. > > > > > > > > > James > > > > > > > > > On Tue, Feb 3, 2009 at 4:25 PM, Jimit <jimitndi...@gmail.com> > > > wrote: > > > > > > > > > > Hi, > > > > > > > > Sorry if this comes as a duplicate post. I think google might > > > have > > > > > > > > eaten my first so here it is again. > > > > > > > > First off, mad props to all of you involved in the FNH - it > > > rocks! > > > > > > > > That said, I've come across what seems to be abugin the > method > > > > > > > > FindMapping<T> of the AutoPersistenceModel class. Here's a > sample > > > > > > > > stack trace: > > > > > > > > > > TestCase 'Can_Write_XML_Mapping_Metadata_To_Folder' > > > > > > > > failed: System.Reflection.TargetInvocationException : > Exception > > > has > > > > > > > > been thrown by the target of an invocation. > > > > > > > > ----> System.IndexOutOfRangeException : Index was outside > the > > > bounds > > > > > > > > of the array. > > > > > > > > at System.RuntimeMethodHandle._InvokeMethodFast(Object > > > target, > > > > > > > > Object > > > > > > > > [] arguments, SignatureStruct& sig, MethodAttributes > > > > > methodAttributes, > > > > > > > > RuntimeTypeHandle typeOwner) > > > > > > > > at System.RuntimeMethodHandle.InvokeMethodFast(Object > > > target, > > > > > Object > > > > > > > > [] arguments, Signature sig, MethodAttributes > methodAttributes, > > > > > > > > RuntimeTypeHandle typeOwner) > > > > > > > > at System.Reflection.RuntimeMethodInfo.Invoke(Object > obj, > > > > > > > > BindingFlags invokeAttr, Binder binder, Object[] parameters, > > > > > > > > CultureInfo culture, Boolean skipVisibilityChecks) > > > > > > > > at System.Reflection.RuntimeMethodInfo.Invoke(Object > obj, > > > > > > > > BindingFlags invokeAttr, Binder binder, Object[] parameters, > > > > > > > > CultureInfo culture) > > > > > > > > at System.Reflection.MethodBase.Invoke(Object obj, > > > Object[] > > > > > > > > parameters) > > > > > > > > at > > > > > > FluentNHibernate.InvocationHelper.InvokeGenericMethodWithDynamicTypeArgumen > > > > > ts > > > > > > > > [T](T target, Expression`1 expression, Object[] > methodArguments, > > > Type > > > > > > > > [] typeArguments) > > > > > > > > at > > > > > FluentNHibernate.AutoMap.AutoPersistenceModel.FindMapping(Type > > > > > > > > type) > > > > > > > > at > > > > > FluentNHibernate.AutoMap.AutoPersistenceModel.CompileMappings() > > > > > > > > C:\Projects\Dev\Source\Core\Tests\Unit Tests > > > > > > > > > \Core.Infrastructure.Data.NHibernate.Tests\MappingTests.cs(47,0): > > > at > > > > > > Core.Infrastructure.Data.NHibernate.Tests.MappingTests.Can_Write_XML_Mappin > > > > > g_Metadata_To_Folder > > > > > > > > () > > > > > > > > --IndexOutOfRangeException > > > > > > > > at > > > > > FluentNHibernate.AutoMap.AutoPersistenceModel.<FindMapping>b__7[T] > > > > > > > > (IMapping t) > > > > > > > > at System.Collections.Generic.List`1.Find(Predicate`1 > > > match) > > > > > > > > at > > > > > FluentNHibernate.AutoMap.AutoPersistenceModel.FindMapping[T]() > > > > > > > > > > The test above simply instantiates a new > AutoPersistenceModel, > > > calls > > > > > > > > MergeWithMappingsFromAssembly<T>() to add some custom > mappings > > > > > > > > (classes inheriting from Automap<T>), calls CompileMappings() > and > > > > > > > > attempts to write them to a folder using WriteMappingsTo(). > > > > > > > > > > I believe the culprit is this line in FindMapping<T>: > > > > > > > > > > // standard AutoMap<T> not found for the type, so > > > looking > > > > > > > > for one for it's base type. > > > > > > > > return (IClassMap)_mappings.Find(t => t.GetType > > > > > > > > ().GetGenericArguments()[0] == typeof(T).BaseType); > > > > > > > > Because _mappings contains instances of classes that are > > > > ... > > > > read more ยป > > > --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Fluent NHibernate" group. To post to this group, send email to fluent-nhibernate@googlegroups.com To unsubscribe from this group, send email to fluent-nhibernate+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/fluent-nhibernate?hl=en -~----------~----~----~----~------~----~------~--~---