Created
January 23, 2011 21:21
-
-
Save JeremySkinner/792450 to your computer and use it in GitHub Desktop.
A little strongly-typed wrapper around WebMatrix.Data - this is now its own project at https://github.com/JeremySkinner/WebMatrix.Data.StronglyTyped
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
// WebMatrix.Data's Query method returns an IEnumerable<dynamic> | |
// While this is great for simple scenarios, if you want to add behaviour to your DB objects | |
// then it can be a pain. Here's a simple wrapper that adds a strongly-typed Query method | |
// This is a simple implementation and could be improved. | |
// Represents a table in the database | |
public class User { | |
public int Id { get; set; } | |
public string Name { get; set; } | |
} | |
// Demo code | |
internal class Program { | |
static void Main(string[] args) { | |
using (var db = Database.Open("Test")) { | |
var users = db.Query<User>("select * from Users"); | |
foreach (var user in users) { | |
Console.WriteLine(user.Id + " " + user.Name); | |
} | |
} | |
Console.ReadKey(); | |
} | |
} |
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
public static class DataExtensions { | |
public static IEnumerable<T> Query<T>(this Database db, string commandText, params object[] args) { | |
var queryResults = db.Query(commandText, args); | |
var mapper = Mapper<T>.Create(); | |
return (from DynamicRecord record in queryResults select mapper.Map(record)).ToList(); | |
} | |
} |
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
public class Mapper<T> { | |
private Func<T> factory; | |
private Dictionary<string, Action<T, object>> setters = new Dictionary<string, Action<T, object>>(); | |
private static Lazy<Mapper<T>> _instance = new Lazy<Mapper<T>>(() => new Mapper<T>()); | |
private Mapper() { | |
factory = CreateActivatorDelegate(); | |
foreach (var property in typeof(T).GetProperties()) { | |
if (property.CanWrite) { | |
setters[property.Name] = BuildSetterDelegate(property); | |
} | |
} | |
} | |
public T Map(DynamicRecord record) { | |
var instance = factory(); | |
foreach(var column in record.Columns) { | |
Action<T, object> setter; | |
if(setters.TryGetValue(column, out setter)) { | |
setter(instance, record[column]); | |
} | |
} | |
return instance; | |
} | |
public static Mapper<T> Create() { | |
return _instance.Value; | |
} | |
private static Func<T> CreateActivatorDelegate() { | |
return CreateActivatorDelegate(typeof(T).GetConstructor(Type.EmptyTypes)); | |
} | |
private static Func<T> CreateActivatorDelegate(ConstructorInfo constructor) { | |
return Expression.Lambda<Func<T>>(Expression.New(constructor)).Compile(); | |
} | |
private static Action<T, object> BuildSetterDelegate(PropertyInfo prop) { | |
var instance = Expression.Parameter(typeof(T), "x"); | |
var argument = Expression.Parameter(typeof(object), "v"); | |
var setterCall = Expression.Call( | |
instance, | |
prop.GetSetMethod(true), | |
Expression.Convert(argument, prop.PropertyType)); | |
return (Action<T, object>)Expression.Lambda(setterCall, instance, argument).Compile(); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment