I'm fooling around with creating a small SQL library with a fluent API and want to do something like this:
var person = connection.GetOne<Person>("select * from [Person] where [Id] = 1")
.WithMany<Pet>("select * from [Pet] where [PersonId] = 1")
.WithMany<Address>("select * from [Address] where [PersonId] = 1]")
.Build((person, pets, addresses) =>
{
person.Pets = pets;
person.Addresses = addresses;
return person;
});
I've built plenty of fluent API's before but all have been much more simple and did not rely on generics so heavily. My question is specifically how to go about implementing the Build() end function. I'm not sure if it's even possible (doesn't seem like it but maybe using Expression is the key?) but how can I keep track of the generic types specified in the calls to the higher chain methods (e.g. GetOne<>(), WithMany<>()) so that when the .Build() is called the Func<> that is required is of the correct types?
In the example above I'd want the Func<> to be Func<Person, IEnumerable<Pet>, IEnumerable<Address>> so that the developer can construct the root item (person) in whatever manner they need to - in this case, populating a couple collections with the results of one->many queries.
Is there any way to do this or am I out of luck? It seems like a lot of places I've looked to for similar things do the whole:
Func<In1, TResult>
Func<In1, In2, TResult>
Func<In1, In2, In3, TResult>
...etc, etc
...type of thing which obviously limits you to a max number of parameters for the function.
Any help or pointers would be much appreciated.