Created
September 28, 2012 06:15
-
-
Save phillip-haydon/3798206 to your computer and use it in GitHub Desktop.
Dynamic Chained API (playing around to see possibilities)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Dynamic; | |
using System.Linq; | |
using System.Reflection; | |
using Raven.Client; | |
using Raven.Client.Document; | |
using Raven.Json.Linq; | |
namespace ChainedAPISample | |
{ | |
class Program | |
{ | |
static void Main(string[] args) | |
{ | |
var documentStore = (new DocumentStore() | |
{ | |
DefaultDatabase = "Testing", | |
Url = "http://localhost:8080" | |
}).Initialize(); | |
using (dynamic chainer = documentStore.OpenDynamicSession()) | |
{ | |
chainer.Posts.insert(new | |
{ | |
Name = "Rabbit" | |
}, "909"); | |
chainer.Posts.Insert(new | |
{ | |
Name = "Banana" | |
}, "123"); | |
chainer.People.insert(new | |
{ | |
FirstName = "Phillip" | |
}, "1"); | |
chainer.People.Insert(new | |
{ | |
FirstName = "Prabir" | |
}, "2"); | |
chainer.SaveChanges(); | |
} | |
using (dynamic chainer = documentStore.OpenDynamicSession()) | |
{ | |
dynamic result = chainer.Posts.load(123); | |
Console.WriteLine(result.Name); | |
dynamic result2 = chainer.Posts.Load(909); | |
Console.WriteLine(result2.Name); | |
dynamic result3 = chainer.People.load(1); | |
Console.WriteLine(result3.FirstName); | |
dynamic result4 = chainer.People.Load(2); | |
Console.WriteLine(result4.FirstName); | |
} | |
Console.ReadKey(); | |
} | |
} | |
public class Chainer : DynamicObject, IDisposable | |
{ | |
protected IDocumentSession Session { get; set; } | |
public Chainer(IDocumentSession session) | |
{ | |
Session = session; | |
} | |
public override bool TryGetMember(GetMemberBinder binder, out object result) | |
{ | |
result = new ChainBuilder(this, Session, binder.Name); | |
return true; | |
} | |
private class ChainBuilder : DynamicObject | |
{ | |
private dynamic OriginalObject { get; set; } | |
private IDocumentSession Session { get; set; } | |
private string CollectionName { get; set; } | |
private static Type documentSessionType = typeof (IDocumentSession); | |
public ChainBuilder(DynamicObject originalObject, IDocumentSession session, string collection) | |
{ | |
OriginalObject = originalObject; | |
Session = session; | |
CollectionName = collection; | |
} | |
public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result) | |
{ | |
if (binder.Name.Equals("load", StringComparison.OrdinalIgnoreCase)) | |
{ | |
var generic = GetLoadMethod(); | |
var id = CollectionName.ToLower() + "/" + args[0]; | |
result = generic.Invoke(Session, new object[] { id }); | |
return true; | |
} | |
if (binder.Name.Equals("insert", StringComparison.OrdinalIgnoreCase)) | |
{ | |
MethodInfo method = GetStoreMethod(); | |
var id = CollectionName.ToLower() + "/" + args[1]; | |
var objectToStore = args[0] as object; | |
method.Invoke(Session, new []{objectToStore, id}); | |
RavenJObject metadata = Session.Advanced.GetMetadataFor(objectToStore); | |
metadata["Raven-Entity-Name"] = CollectionName; | |
result = null; | |
return true; | |
} | |
return base.TryInvokeMember(binder, args, out result); | |
} | |
private static MethodInfo GetLoadMethod() | |
{ | |
MethodInfo method = documentSessionType.GetMethods().FirstOrDefault(x => x.Name == "Load"); | |
MethodInfo generic = method.MakeGenericMethod(typeof (object)); | |
return generic; | |
} | |
private static MethodInfo GetStoreMethod() | |
{ | |
return documentSessionType.GetMethods() | |
.Where(x => | |
{ | |
if (x.Name != "Store") | |
return false; | |
var methodParams = x.GetParameters(); | |
if (methodParams.Length != 2) | |
return false; | |
if (methodParams[1].ParameterType == typeof(string)) | |
return true; | |
return false; | |
}) | |
.FirstOrDefault(); | |
} | |
} | |
public void SaveChanges() | |
{ | |
Session.SaveChanges(); | |
} | |
public void Dispose() | |
{ | |
Session.Dispose(); | |
} | |
} | |
public static class DynamicSessionExtension | |
{ | |
public static Chainer OpenDynamicSession(this IDocumentStore store) | |
{ | |
var chainer = new Chainer(store.OpenSession()); | |
return chainer; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This could be improved to support named parameters.