Category Archives: Reflection

Creating Complex Tables using SQLite.Net

Based on this earlier post, I returned to my test project to find that it didn’t actually pass anymore. The first issue was that the test couldn’t locate Sqllite3.dll.

Thanks to this question on every programmers favourite web site, I realised that I needed to add an extension for SQLite.

The next issue was when I tried to add a test to create a complex table:

complex1

Don’t know about [EntityName].

What I mean by a complex table, and the thing that CreateTable doesn’t like, is an entity that references another entity (the same is true if you try to reference the same entity).

Finally, you’re not allowed to use the System.Object type:

Complex2

A fix

It is my understanding that, if you can get it to work with SQLite, Entity Framework will solve this problem for you. I took more of a roll-your-own approach. The key issue here is that you want SQLite to not try to serialise the second object; and for this, you can use the [Ignore] attribute:

private ProductCategory _category;
 
[Ignore]
public ProductCategory Category
{
    get { return _category; }
    set
    {
        _category = value;
        RaisePropertyChanged();
    }
}

So, that stops it crashing. The next part is largely dependent on your data: if you have a basic primary / foreign key one-to-n mapping then this will work; however, anything more complex, and you’ll probably have to write a custom abstraction for the data. All that said, my solution starts with a base entity class:

public abstract class BaseDataEntity : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;
 
    protected void RaisePropertyChanged([CallerMemberName] string propertyName = null)
    {
        var handler = PropertyChanged;
        if (handler != null)
            handler(this, new PropertyChangedEventArgs(propertyName));
    }
 
    public abstract string Key { get; set; }
}

The PropertyChanged goes without saying (it’s like the roads), but the interesting part is the Key. Based on the code above, each entity needs a uniquely identifiable key; in this case, it’s a string; however, this can be any primitive type. In the derived class, you’ll need to map the type to the data; for example:

 
[Ignore]
public ProductCategory Category
{
    get { return _category; }
    set
    {
        _category = value;
        RaisePropertyChanged();
    }
}
 
public string CategoryRef
{
    get { return Category.Key; }
    set
    {
        if (Category == null)
        {
            Category = new ProductCategory()
            {
                Key = value
            };
        }
    }
}        

I’ll explain CategoryRef later on.

The next thing is to put some logic into the data access (I simply created a DataAccessBase class to sit on top of the SQLite data manipulation. Here is the abstraction to add a record:

 
public void Add(Type objType, object t)
{
    _connection.Insert(t);
 
    // Look for any ignored properties
    var ignored = objType                
        .GetProperties().Where(p =>
            p.CustomAttributes.Any(a => a.AttributeType == typeof(SQLite.Net.Attributes.IgnoreAttribute)));
 
    // For each, look for a reference
    foreach (var p in ignored)
    {
        // Determine the type first and get the value
        Type propertyType = p.PropertyType;
        var propertyValue = p.GetValue(t);
 
        // Recursively call this function to add the reference
        Add(propertyType, propertyValue);
    }
}

As you can see, for each reference, it simply recursively calls itself to add that, too. This will spectacularly fall down if you have a circular reference (so don’t do that, or don’t use this if you do).

Next is the Get:

 

public T Get<T>(string key) where T : class
{
    T data = _connection.Get<T>(key);
 
    var ignored = typeof(T)
        .GetProperties()
        .Where(p => p.GetCustomAttributes(typeof(SQLite.Net.Attributes.IgnoreAttribute), inherit: true).Any())
        .ToList();
 
    // For each, look for a reference
    foreach (var p in ignored)
    {
        // Get the reference property
        string propName = $"{p.Name}Ref";
        PropertyInfo refProp = typeof(T).GetProperty(propName);
 
        // Get its value (we know it's a string)
        string val = refProp.GetValue(data).ToString();
 
        // Determine the type first and get the value
        Type propertyType = p.PropertyType;
        
        var mapping = _connection.TableMappings.First(m => m.MappedType == propertyType);
        var rec = _connection.Find(val, mapping);
 
        // Update the property
        p.SetValue(data, rec);
 
    }
}

Here, I’m using a convention based approach; so, where I reference a separate class, I also have separate property called [Class]Ref; which you can see earlier on in the example of the entity code.

Conclusion

And that’s it; I make no assertions about edge cases, but for basic data that references other basic data, this works fine.

Acknowledgements

I have a great deal of help in creating this, but mainly just from random search results; however, I did ask a question on Stack Overflow

Testing by Interface

Given a standard interface, how to retrieve all implementing classes and run the interface methods.

Unit testing through test driven development is definitely a good idea; but what if you have a number of methods that all effectively do the same thing; that is, each method might do something completely different, but as far as it’s interface goes, it’s identical.

Imagine, for example, that you have a method that calls to the DB, and accepts a number of parameters in, and returns a given parameter. In a unit testing scenario, the DB would be mocked out, and the method called directly from the unit test. Okay, so in this case, you may want some test coverage that your methods call a mocked out DB function, don’t crash, accept a given object, accept null, etc…

Facing the same problem, it occurred to me that it should be possible to write a single test method that would test every existing and future implementation of this, without having to laboriously re-create the test each time I create a method; what’s more, as soon as I create my method name that implements the interface, I get a failing test.

Below is an interface and a test class; it is entirely for the purpose of illustration:

    public class ModelClass
    {
        public string TestProperty { get; set; }
    }


    public interface ITest
    {
        void method1();

        void method2(ModelClass model, int i);
    }

    public class Class1 : ITest
    {
        public void method1()
        {
        }

        public void method2(ModelClass model, int i)
        {
            if (model == null) throw new Exception("test");
            //if (string.IsNullOrWhiteSpace(model.TestProperty)) throw new Exception("Doh");
        }
    }

    public class Class2 : ITest
    {
        public void method1()
        {
            //throw new NotImplementedException();
        }

        public void method2(ModelClass model, int i )
        {
            
        }
    }

    public class Class3
    {
        public void  NonInterfaceMethod(ModelClass model)
        {
            throw new Exception("Doh!");
        }
    }

    public class Class4 : ITest
    {
        public void method1()
        {
            //throw new NotImplementedException();
        }

        public void method2(ModelClass model, int i)
        {
            
        }

        public void test()
        {

        }
    }

 

As you can see, there are a number of interface, and non-interface methods here. There’s nothing particularly interesting, although have a look at Class1.method2(), which should do nothing, but switching the statements should cause a runtime error, if my method works. Also, have a look at Class3.NonInterfaceMethod() – this should never be called, but will throw an exception if it is.

The following is the test code:

        [TestMethod]
        public void TestITestImplementations()
        {
            // Use reflection to get the available methods for the interface
            Type desiredType = typeof(ITest);
            Assembly assembly = desiredType.Assembly;
            var interfaceMethods = desiredType.GetMethods();
            
            // Iterate through each implementation of the interface
            foreach (Type type in assembly.GetTypes())
            {
                if (desiredType.IsAssignableFrom(type) && !type.IsInterface)
                {
                    // Where an implementation is found, instantiate it 
                    // and build a list of available methods to call
                    var classInstance = Activator.CreateInstance(type, null);
                    var methods = type.GetMethods()
                        .Where(m => interfaceMethods.Any(i => i.Name == m.Name)
                            && m.IsPublic
                            && !m.DeclaringType.Equals(typeof(object)));
                    foreach(var method in methods)
                    {
                        // Establish the available parameters and pass them to the call
                        var p = method.GetParameters();
                        object[] p2 = p.Select(a => Activator.CreateInstance(a.ParameterType)).ToArray();

                        try
                        {
                            // Call the method and, where a value should be returned, ensure one is
                            object result = method.Invoke(classInstance, p2);
                            Assert.IsFalse(method.ReturnType != typeof(void) && result == null);
                        }
                        catch(Exception ex)
                        {
                            // Where an error is thrown, print a sensible error
                            Assert.Fail("Call failed: {0}.{1}\nException: {2}", 
                                type.Name, method.Name, ex);
                        }
                    }
                }
            }            
        }

The code above is relatively straight-forward and, if I’m being honest, is only a cursory test. It tests that the methods can be called without throwing an error and, where a value should be returned, checks that it’s not null.

Obviously, it might be perfectly valid that it is null, or an exception might be the desired behaviour. This code is basically just a starting point, but it does provide some very basic test coverage where otherwise, there might be none.

It is also true to say that the code doesn’t deal with overloads, which are not necessary in my particular circumstance.