[Mono-list] Fun and games with Sqlite and System.Reflection

Paul Johnson paul at all-the-johnsons.co.uk
Wed Apr 9 12:38:02 UTC 2014


Hi,

I have a very simple SQLite database class which I'm using 
System.Reflection to serialise and use within my DBManager class.

My class looks like this (it's a test case to try and get things working 
before I integrate it)

public class dbclass
{
     [PrimaryKey]
     public string Id { get; set; }

     public string Test { get; set; }

     public DateTime Today { get; set; }

     [Ignore]
     public List<string> ListTest { get; set; }

     public override string ToString()
     {
         return string.Format("[dbclass: Id={0}, Test={1}, 
ListTest={2}]", Id, Test, ListTest);
     }
}
When I serialise this class, the Ignore attribute used for Sqlite is 
ignored as it's not a System.Reflection attribute. Without it, the 
List<T> tries to be processed and causes the code to crash as it has 
nothing in the database for it (and Lists are supported under SQlite 
anyway!)

I've checked on MSDN and there doesn't seem to be an equivalent of the 
Ignore attribute which is a bit of a pain.

Within my dbclass, is it possible to set the reflection attribute to 
something so I can intercept and ignore the property I need to ignore 
(in this case the List)?

My code that does the processing looks like this (no giggling at the back!)

using System;
using System.Collections.Generic;
using System.Reflection;
using System.Linq.Expressions;
using System.Text;
using SQLite;

public class dbclass
     {
         [PrimaryKey]
         public string Id { get; set; }

         public string Test { get; set; }

         public DateTime Today { get; set; }

         [Ignore]
         public List<string> ListTest { get; set; }

         public override string ToString()
         {
             return string.Format("[dbclass: Id={0}, Test={1}, 
ListTest={2}]", Id, Test, ListTest);
         }
     }

     class TestClass
     {
         public TestClass()
         {
             var db = new dbclass()
             {
                 Id = Guid.NewGuid().ToString(),
                 Test = "Hello",
                 Today = DateTime.Now
             };
             Console.WriteLine("{0}", GetInsertQuery(db));
         }

         private readonly Dictionary<Type, Func<Object, String>> 
queryBuilders = new Dictionary<Type, Func<object, string>>();

         public string GetInsertQuery(Object entity)
         {
             var type = entity.GetType();
             if (!queryBuilders.ContainsKey(type))
             {
                 var param = Expression.Parameter(typeof(Object), "entity");
                 var typedObject = Expression.Variable(type, "obj");
                 var stringBuilder = 
Expression.Variable(typeof(StringBuilder), "sb");

                 var appendString = 
typeof(StringBuilder).GetMethod("Append", new[] { typeof(String) });
                 var objectToString = typeof(Object).GetMethod("ToString");

                 var code = new List<Expression>();
                 code.Add(Expression.Assign(typedObject, 
Expression.Convert(param, type)));
                 code.Add(Expression.Assign(stringBuilder, 
Expression.New(typeof(StringBuilder))));

                 code.Add(Expression.Call(stringBuilder, appendString, 
Expression.Constant(string.Format("INSERT INTO {0} (", type.Name))));

                 var properties = type.GetProperties();

                 for (int i = 0; i < properties.Length - 1; i++)
                 {
                     code.Add(Expression.Call(stringBuilder, 
appendString, Expression.Constant(properties[i].Name)));
                     code.Add(Expression.Call(stringBuilder, 
appendString, Expression.Constant(", ")));
                 }

                 code.Add(Expression.Call(stringBuilder, appendString, 
Expression.Constant(properties[properties.Length - 1].Name)));

                 code.Add(Expression.Call(stringBuilder, appendString, 
Expression.Constant(") VALUES (")));

                 for (int i = 0; i < properties.Length - 1; i++)
                 {
                     code.Add(Expression.Call(stringBuilder, 
appendString, Expression.Constant("'")));
                     code.Add(Expression.Call(stringBuilder, 
appendString, Expression.Call(Expression.Property(typedObject, 
properties[i]), objectToString)));
                     code.Add(Expression.Call(stringBuilder, 
appendString, Expression.Constant("', ")));
                 }

                 code.Add(Expression.Call(stringBuilder, appendString, 
Expression.Constant("'")));
                 code.Add(Expression.Call(stringBuilder, appendString, 
Expression.Call(Expression.Property(typedObject, 
properties[properties.Length - 1]), objectToString)));
                 code.Add(Expression.Call(stringBuilder, appendString, 
Expression.Constant("', ")));

                 code.Add(Expression.Call(stringBuilder, appendString, 
Expression.Constant(");")));


                 code.Add(Expression.Call(stringBuilder, "ToString", new 
Type[] { }));

                 var expression = Expression.Lambda<Func<Object, 
String>>(Expression.Block(new[] { typedObject, stringBuilder }, code), 
param);
                 queryBuilders[type] = expression.Compile();
             }

             string f = queryBuilders[type](entity);
             return f;
         }

Dies if you add a List<T> into the class being passed in

TIA

Paul
-- 
Out now from Packt Publishing - "Xamarin Mobile Application Development 
for iOS" - my first book
http://www.packtpub.com/xamarin-mobile-application-development-for-ios/book


More information about the Mono-list mailing list