2017-09-06 4 views
2

Je tente de générer dynamiquement et d'exécuter le SQL pour Dapper dans le but de simplement transmettre un type et le SQL est généré et exécuté dynamiquement.Dynamique Func <> pour mappage de requête Dapper

classes Exemple:

public class User 
{ 
    [Key] 
    public int UserId { get; set; } 
    public Address Address { get; set; } 
} 
public class Address 
{ 
    [Key] 
    public int UserId { get; set; } 
    public string PostCode { get; set; } 
} 

aura pour effet de faire fonctionner les éléments suivants:

// sql: "SELECT User.UserId, Address.UserId, Address.PostCode FROM User LEFT JOIN Address ON Address.User = User.UserId"... // auto generated from 'User' type including join to 'Address'; 

connection.Query<User, Address, User>(sql, /*** map argument needs to be dynamic Func<> ***/); 

Alors, étant donné ces types User & Address qui ne sont connus lors de l'exécution, comment puis-je générer le délégué approprié Func<User, Address, User> à passer à l'argument map?

Func<User, Address, User> map = (u, a) => { 
    u.Address = a; 
    return u; 
} 

Le examples que je l'ai vu pour la création d'un Func<> utilisant la réflexion suppose les types sont connus, dans mon cas, ils ne sont pas les arguments de type différent (Func <,>/Func < ,,>/Func < ,,,> etc).

Toute aide appréciée. Je vais continuer à travailler à travers des exemples en utilisant des expressions pour voir si quelque chose colle.

+0

https://stackoverflow.com/a/21731667/1264882 – WithMetta

Répondre

1

Ceci est aussi proche que je l'ai eu. J'ai essayé de cloner le repo de Dapper pour creuser comment fonctionne la méthode Query(), mais j'utilise une ancienne version de Visual Studio.

public static class DynamicFuncHelper 
{ 
    public static Delegate CreateFunc(Type type1, Type type2) 
    { 
     Type funcType = typeof(Func<,,>).MakeGenericType(type1, type2, type1); 
     MethodInfo method = 
      typeof(DynamicFuncHelper<,>) 
      .MakeGenericType(type1, type2) 
      .GetMethod("SetAddressProperty", 
       BindingFlags.Public | BindingFlags.Static 
      ); 
     return Delegate.CreateDelegate(funcType, method); 
    } 
} 

public static class DynamicFuncHelper<T,U> 
    where T : class 
    where U : class 
{ 
    public static T SetAddressProperty(T obj1, U obj2) 
    { 
     obj1.GetType().InvokeMember("Address", 
      BindingFlags.Instance | BindingFlags.Public | BindingFlags.SetProperty, 
      Type.DefaultBinder, obj1, new[] { obj2 }); 
     return obj1; 
    } 
} 

Passé ce test unitaire

[TestClass] 
public class DynamicFuncTest 
{ 
    [TestMethod] 
    public void TestDynamicMapper() 
    { 
     var actualUser = new User { UserId = 1 }; 
     var actualAddress = new Address { PostCode = "12345", UserId = 1 }; 
     var testSetAddress = DynamicFuncHelper.CreateFunc(typeof(User), typeof(Address)); 
     var delegateResult = testSetAddress.DynamicInvoke(actualUser, actualAddress); 
     Assert.AreEqual(actualUser, delegateResult, "Delegate result was not actualUser"); 
     Assert.AreEqual(actualAddress, actualUser.Address, "User address was not expected address"); 
    } 
} 
+0

Hey, merci pour votre réponse. Cela semble prometteur mais je suis toujours coincé avec le fait qu'il pourrait y avoir un certain nombre d'arguments de type pour 'Func'. J'ai trouvé [cette bibliothèque] (https://www.nuget.org/packages/Dapper.Mapper/) qui semble résoudre le problème - je peux juste finir par tirer cela pour résoudre l'argument de la carte. –