5

Background

I am using Linq to SQL and thus have a generated DBML file containing auto-generated classes. Part of the generation process creates partial methods for certain actions, and in my case the two methods I am interested in related to the Insert and Update of table records. These partial methods are generated per each Table created in the DBML designer, for example:

partial void InsertMyTable(MyTable instance);
partial void UpdateMyTable(MyTable instance);

Now part of the design of my application requires that these two partial methods are always implemented for every single table. (They are essentially used to add a timestamp to the record being inserted/updated).

Requirement

I have a unit test project, and although this may not be common practice I want to include a few tests that ensure certain things have been implemented properly. In this case I want to ensure that the developers have remembered to implement the partial methods mentioned above (I do NOT care about the actually implementation, only that they have been implemented).

Problem

What I need to do is use reflection to check if each partial method has been implemented, but I am having trouble working out how to determine that.

Attempted Efforts

So far I have managed to get a list of methods contained within the data context, and I am able to compare that with the methods expected for each table. The problem is that I can't find a way to determine if a given partial method actually has an implementation:

var methods = (typeof(MyDataContext)).GetMethods(BindingFlags.NonPublic | BindingFlags.Instance);
foreach (var method in methods) 
{
    Console.WriteLine(method.Name);
    //how to check if method is implemented, or just an unimplemented partial
}
musefan
  • 47,875
  • 21
  • 135
  • 185
  • 2
    Wouldn't it be easier to provide a default implementation of `throw new NotImplementedException()`? – James Nov 13 '13 at 13:16
  • @James: The partial method is auto-generated, which means the developer needs to remember to implement it each time a new table is add to the DBML designer – musefan Nov 13 '13 at 13:17
  • Or perhaps create an attribute that you tack onto the implemented methods and see if it exists in your check. – gleng Nov 13 '13 at 13:17
  • 6
    Partial methods are new to me, but it seems like at runtime, if it hasn't been implemented, it won't be returned in the GetMethods call as the compiler discards unimplemented partials according to http://msdn.microsoft.com/en-us/library/6b0scde8.aspx – T. Kiley Nov 13 '13 at 13:18
  • BindingFlags.DeclaredOnly should ignore inherited members – oerkelens Nov 13 '13 at 13:18
  • @gleng: Again, the point in these tests in to ensure the developer remembers to implement the partial methods. Adding an attribute would then require them to remember to do that instead – musefan Nov 13 '13 at 13:18

3 Answers3

11

What you have already works. If the partial method doesn't have an implementation, then it does not exist at all. There is no "declaration stub" that you might find by reflection accidentally. Either the partial method has an implementation, or it is removed completely by the compiler.

So basically: if you can't find the method with GetMethod / GetMethods (with the appropriate BindingFlags, as per the question) - then it wasn't implemented.

Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900
  • Yes, you are correct, I hadn't noticed that my list didn't contain those that are not implemented! So the solution is just to check if the method exists at all – musefan Nov 13 '13 at 13:21
2

As an alternative idea (and one that is obvious at compile-time, and which isn't susceptible to problems with obfuscation):

// generated code
public partial class Whatever : ISomeInterface<MyTable>
{
    //...
}

//somewhere else
public interface ISomeInterface<T>
{
    void Insert(T instance);
    void Update(T instance);
}

Now the compiler won't let the user proceed without implementing this interface completely, presumably in a partial class:

partial class Whatever
{
    public void Insert(MyTable instance) {...}
    public void Update(MyTable instance) {...}
}

(note they can still use explicit interface implementation, but you should use that interface yourself when accessing the data; avoids even more reflection)

Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900
  • I see what you mean here, however it doesn't help in my situation as the class is auto-generated – musefan Nov 13 '13 at 13:34
  • @musefan if it is you that is auto-generating them, then that shouldn't be an issue; if it *isn't* you, then: indeed – Marc Gravell Nov 14 '13 at 09:54
0

When I ran into the same problem I solved it as follows:

var Method = (typeof(Entities))
.GetMethods(System.Reflection.BindingFlags.NonPublic |
System.Reflection.BindingFlags.Instance)
.FirstOrDefault(x => x.Name == "SomeMethodShouldBeOnPartialClass");
if (Method != null) Method.Invoke(this,null);
Developer
  • 788
  • 6
  • 10