Hi Paul

I will be applying your patch as the first fix for the problem, however I've
just not had any time yet. I may at somepoint look for a larger refactoring,
but I think one way or another dropping down your method will be essential
at somepoint in the process.

Cheers

Andy

On Tue, Aug 26, 2008 at 9:04 PM, Paul Batum <[EMAIL PROTECTED]> wrote:

> Hey Andy,
>
> I was wondering if you have decided where to go with this code? I thought
> my patch would be a good option if you don't want to engage in a larger
> refactoring.
>
> Paul Batum
>
>
> On Sun, Aug 17, 2008 at 6:20 PM, Paul Batum <[EMAIL PROTECTED]> wrote:
>
>> Hey Andy,
>>
>> I decided to tackle your problem from a different angle to Chad. It sounds
>> like Chad went to the root of the problem by making non generic methods. I
>> came up with a less fragile way of invoking the generic methods using
>> reflection. My solution replaces this:
>>
>> // Merge Mappings together
>> var findAutoMapMethod = typeof(AutoMapper).GetMethod("MergeMap");
>> var genericfindAutoMapMethod = findAutoMapMethod.MakeGenericMethod(obj);
>> genericfindAutoMapMethod.Invoke(autoMap, new[] { mapping });
>>
>> With this:
>>
>> InvocationHelper.InvokeGenericMethodWithDynamicTypeArguments(
>>                 autoMap, a => a.MergeMap<object>(null), new[] { mapping },
>> obj);
>>
>> Here is the implementation of that method:
>>
>>         public static object
>> InvokeGenericMethodWithDynamicTypeArguments<T>(T target, Expression<Func<T,
>> object>> expression, object[] methodArguments, params Type[] typeArguments)
>>         {
>>             var methodInfo = ReflectionHelper.GetMethod(expression);
>>             if (methodInfo.GetGenericArguments().Length !=
>> typeArguments.Length)
>>                 throw new ArgumentException(
>>                     string.Format("The method '{0}' has {1} type
>> argument(s) but {2} type argument(s) were passed. The amounts must be
>> equal.",
>>                     methodInfo.Name,
>>                     methodInfo.GetGenericArguments().Length,
>>                     typeArguments.Length));
>>
>>             return methodInfo
>>                 .GetGenericMethodDefinition()
>>                 .MakeGenericMethod(typeArguments)
>>                 .Invoke(target, methodArguments);
>>         }
>>
>> This is sturdier because a refactoring of the MergeMap method would flow
>> to the lambda. Obviously it is still somewhat fragile because there is no
>> guarantee that the right number of type arguments is passed, hence the
>> runtime check.
>>
>> The patch is attached to this email. I figure that you will probably want
>> to go down the path that Chad followed, but perhaps this implementation will
>> be useful trick when you don't have the luxury of modifying the API to be
>> non-generic.
>>
>> Paul Batum
>>
>>
>>
>> On Sun, Aug 17, 2008 at 3:28 PM, Andrew Stewart <
>> [EMAIL PROTECTED]> wrote:
>>
>>>  Hi Chad
>>>
>>>
>>>> Will this be called directly by people, or is this mostly internal API
>>>> stuff?
>>>
>>>
>>> The crappy code is only internal and tests should now fail if it's
>>> broken, which is nice to know. I think I know what you mean and I'll try and
>>> tidy that code up shortly, thanks for the offer to pair over this it may
>>> come in useful, but i'd like to have a go at it myself for now. I'll give
>>> you a shout if I get stuck though, if it's ok with you.
>>>
>>> Cheers
>>>
>>> Andy
>>>
>>>
>>>   On Sat, Aug 16, 2008 at 1:02 AM, Chad Myers <[EMAIL PROTECTED]>wrote:
>>>
>>>>  I did a spike and got my head around it. Basically, you have a bunch
>>>> of generic methods and then you're treating them non-generically.
>>>>
>>>>
>>>>
>>>> Will this be called directly by people, or is this mostly internal API
>>>> stuff?
>>>>
>>>>
>>>>
>>>> I was able to create an IAutoMap rather than have AutoMap<T>,
>>>> IAutoPartMapper instead of the various part mappers (IAutoMapper was
>>>> confusing because there's an AutoMapper<T>, but it wasn't an IAutoMapper,
>>>> IAutoMapper is really something like IAutoPartMapper, etc).
>>>>
>>>>
>>>>
>>>> Anyhow, if you use interfaces for these things and make them non-generic
>>>> (i.e. don't make it Foo<T>, just make methods like Foo(Type theType)).
>>>>
>>>>
>>>>
>>>> Make the people-facing fluent interfaces generic <T>, but all the
>>>> internal stuff non-generic otherwise your life will be very painful (as
>>>> you've already found out).
>>>>
>>>>
>>>>
>>>> I don't want to commit my spike code because it's not tested and it's
>>>> sloppy, but maybe we can pair on this sometime if you want, or if you want
>>>> to research this yourself, etc.
>>>>
>>>>
>>>>
>>>> -c
>>>>
>>>>
>>>>
>>>> *From:* fluent-nhibernate@googlegroups.com [mailto:
>>>> [EMAIL PROTECTED] *On Behalf Of *Andrew Stewart
>>>> *Sent:* Friday, August 15, 2008 7:51 AM
>>>> *To:* fluent-nhibernate@googlegroups.com
>>>> *Subject:* [fluent-nhib] Re: Ayende on Fluent nHibernate - AutoMap
>>>>
>>>>
>>>>
>>>> Hello
>>>>
>>>>
>>>>
>>>> I've just checked this in and it seems to work,
>>>>
>>>>
>>>>
>>>>  var persistenceModel = new
>>>> AutoPersistenceModel(Assembly.GetAssembly(typeof(PlotMap)));
>>>> persistenceModel.AddEntityAssembly(Assembly.GetAssembly(typeof
>>>> (Address)), t => (t.Namespace == "Mdis.Entities" && ( t.BaseType ==
>>>> typeof(object))));
>>>> persistenceModel.Configure(cfg);
>>>>
>>>>
>>>>
>>>> The first assembly is the assembly containing your maps, the second is
>>>> the assembly containing your entities (I'm assuming you have two assemblies
>>>> for SoC, but there's no reason why these can't be the same). Then I've
>>>> created an AutoMap which inherits from ClassMap, this is so I don't dirty 
>>>> up
>>>> the base class with my little requirements, essentially what properties 
>>>> have
>>>> already been mapped(to prevent duplication).
>>>>
>>>>
>>>>
>>>> Example
>>>>
>>>> public class PlotMap : AutoMap<Plot>
>>>> {
>>>>    public PlotMap()
>>>>    {
>>>>       HasManyToMany<Service>(p => p.Services);
>>>>    }
>>>> }
>>>>
>>>> What happens is, first it loads in your automap's then in maps in extra
>>>> unmapped properties and entities(hope that makes sense). So you only need 
>>>> to
>>>> specify exceptions to the rule everything else will be mapped straight out
>>>> the box as if by magic. Now my next challenge will be making this a bit 
>>>> more
>>>> fluent and specifying conventions across the board as of Chad's suggestion
>>>> below:
>>>>
>>>>
>>>>
>>>>   var model = AutoPersistenceModel
>>>>        .MapEntitiesFromAssemblyOf<AutoMapTests>()
>>>>        .Where(t => t.Namespace == "FluentNHibernate.AutoMap.Test")
>>>>        .ForTypesThatDeriveFrom<DomainEntity>(map =>
>>>>                                                  {
>>>>
>>>> map.UseIdentityForKey(e => e.Id, "Id");
>>>>                                                  });
>>>>
>>>>
>>>>
>>>> Plus if anyone can think of a nice way to replace the contents of
>>>> AutoPersistanceModel.AddEntityAssembly, which strict typing let me know.
>>>>
>>>>
>>>>
>>>> Hope you like it, so far.
>>>>
>>>>
>>>>
>>>> Andy
>>>>
>>>>
>>>>
>>>>
>>>>
>>>>
>>
>
> >
>


-- 
=================
I-nnovate Software - Bespoke Software Development, uk wirral.
http://www.i-nnovate.net

--~--~---------~--~----~------------~-------~--~----~
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 [EMAIL PROTECTED]
For more options, visit this group at 
http://groups.google.com/group/fluent-nhibernate?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to