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
>>>
>>>
>>>
>>>
>>> >>>
>>>
>

--~--~---------~--~----~------------~-------~--~----~
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