mercredi 7 septembre 2016

Error when binding generic method delegate - Signature or Security Transparency

I'm creating some delegates to speed up database queries from generic methods and have stumbled upon the following error:

Cannot bind to the target method because its signature or security transparency is not compatible with that of the delegate type.

I have two methods which create these delegates, both with similar structures, but one works and the other doesn't. The only major difference between them is that the one which doesn't work has more parameters and returns a List with a generic type where as the working one only takes a single parameter and returns a single value of a declared type rather than a generic T.

Here's some example code:

The Method

public List<T> GetConnections<T>(IElement element, bool getChildren, bool getParents) where T : IConnectionTable, new()
{
    // do some database stuff and return a List<T> where the constraints on
    // T follow the method description above.
}

Creating the Delegate

Simplified for clarity

private Func<IElement, bool, bool, List<IConnectionTable>> GetConnectionsDelegate(string connectionType)
{
    // Get the type element from the passed string.
    Type elementType = Type.GetType(connectionType, true);

    // Create the generic method using that type.
    MethodInfo method = typeof(MyClass).GetMethod("GetConnections", new Type[]{ typeof(IElement), typeof(bool), typeof(bool) });
    MethodInfo generic = method.MakeGenericMethod(elementType);

    // Create a delegate of the method to speed up subsequent queries.
    var converted = (Func<IElement, bool, bool, List<IConnectionTable>>)Delegate.CreateDelegate(typeof(Func<IElement, bool, bool, List<IConnectionTable>>), this, generic);

    // the above line is where it dies
}

The actual code saves the delegate into a private static dictionary so I only have to use reflection once.

If I print out the contents of method and generic it all seems to be correctly converted.

Result StandardOutput:  

System.Collections.Generic.List`1[T] GetConnections[T](MyProject.Database.IElement, Boolean, Boolean)
System.Collections.Generic.List`1[MyTestProject.TestConnection] GetConnections[TestConnection](MyProject.Database.IElement, Boolean, Boolean)

My assumption here is that the problems lie in the difference between the generic List vs IConnectionTable List return types but making the method return a non-generic list results in a lot of cast errors in the generic method and is kinda wrong to do anyway. Plus, that code runs fine when tested.

It shouldn't be the difference between the private and public methods as my other delegate creation methods are the same and work fine (I've also tried changing GetConnectionsDelegate to public and it makes no difference.)

Any help would be much appreciated.

ndh





Aucun commentaire:

Enregistrer un commentaire