2016-08-29 4 views
0

J'ai eu une idée et je veux savoir si cela peut marcher. J'ai des classes simples avec des propriétés et je veux générer des accesseurs avec des expressions. Mais à la fin je dois obtenir un Func<Test, string> mais je ne connais pas les types quand je les utilise. Un petit exempleCréer un arbre d'expressions de manière dynamique

class Program 
{ 
    static void Main(string[] args) 
    { 
     Test test = new Test(); 
     test.TestString = "Blubb"; 
     var actionStub = typeof(Helper).GetMethod("CreatePropertyGetter").MakeGenericMethod(new Type[] { test.GetType(), typeof(string)}); 
     dynamic action = actionStub.Invoke(null, new object[] {test.GetType(), "TestString"}); 

     var x = action(test); 
    } 
} 

public class Test 
{ 
    public string TestString { get; set; } 
} 

public static class Helper 
{ 
    public static Func<TType, TPropValueType> CreatePropertyGetter<TType, TPropValueType>(Type type, 
                        string propertyName) 
    { 
     PropertyInfo fieldInfo = type.GetProperty(propertyName); 
     ParameterExpression targetExp = Expression.Parameter(typeof(TType), "target"); 

     MemberExpression fieldExp = Expression.Property(targetExp, fieldInfo); 
     UnaryExpression assignExp = Expression.Convert(fieldExp, typeof(TPropValueType)); 

     Func<TType, TPropValueType> getter = 
      Expression.Lambda<Func<TType, TPropValueType>>(assignExp, targetExp).Compile(); 

     return getter; 
    } 
} 

Le problème est que je ne peux pas appeler l'expression sans dynamique, parce que je ne peux pas coulé simple, à Func<object, object>

Répondre

2

Vous générez (TType target) => target.Something. Au lieu de cela, générer (object target) => (object)((TType)target).Something de sorte que vous pouvez utiliser Func<object, object>.

+0

Merci pour le pouvez-vous s'il vous plaît expliquer un peu plus? – Sebastian

+1

Vous cherchez à créer un 'Func ' de sorte que le paramètre et le corps doivent se conformer à cette signature. Le paramètre doit être de type objet et le corps doit renvoyer l'objet. Ensuite, vous pouvez utiliser Func . – usr

0

On ne sait pas ce que vous demandez exactement, mais voici un exemple comment vous pouvez le faire Func<object, object>:

public static class Helper 
{ 
    public static Func<object, object> CreatePropertyGetter(Type type, string propertyName) 
    { 
     var fieldInfo = type.GetProperty(propertyName); 
     var targetExp = Expression.Parameter(typeof(object), "target"); 
     var fieldExp = Expression.Property(Expression.ConvertChecked(targetExp, type), fieldInfo); 
     var getter = Expression.Lambda<Func<object, object>>(fieldExp,targetExp).Compile(); 
     return getter; 
    } 
}