2010-10-28 21 views
1

Je possède ce code C# qui fonctionne très bien, qui saisit les deux champs et les met dans une liste pour une liste déroulante:C# Fonction qui accepte les paramètres de chaîne: Comment refactoriser pour utiliser quelque chose fortement typé?

var myDDL = GetDDLValues<Product>(myContact, "contactid", "companyname"); 

Je voudrais à prendre les deux paramètres de chaîne dans autre chose que cordes. Ce serait vraiment bien de faire: (! Réflexion par sweko Merci)

GetDDLValues<Product>(myContact, p => p.contactid, p => p.companyname) 

Ce code appelle:

private object GetProperty(object obj, string propertyName) 
{ 
    PropertyInfo pi = obj.GetType().GetProperty(propertyName); 
    object value = pi.GetValue(obj, null); 
    return value; 
} 

public IList<DDLValues> GetDDLValues<T>(IList<T> objectListToMap, 
         string textProperty, string valueProperty) 
{ 
    if(objectListToMap != null && objectListToMap.Count > 0) 
    { 
     Mapper.CreateMap< T, DDLValues>() 
       .ForMember(dest => dest.text, 
          opt => opt.MapFrom(src => textProperty)) 
       .ForMember(dest => dest.value, 
          opt => opt.MapFrom(src => valueProperty)); 
     return Mapper.Map<IList<T>, IList<DDLValues>>(objectListToMap); 
    } 
    else 
    { 
     return null; 
    } 
} 
+0

Dans votre GetDDLValues ​​() la mise en œuvre, voulez-vous dire MapFrom (src => GetProperty (src, TextProperty))? – dahlbyk

Répondre

1

tvanfosson a raison de dire qu'un Select() est le plus simple; si vous voulez utiliser AutoMapper, vous voulez quelque chose comme ça ..

public IList<DDLValues> GetDDLValues<T>(IList<T> objectListToMap, 
         Func<T, string> textSelector, Func<T, string> valueSelector) 
{ 
    if(objectListToMap == null || objectListToMap.Count == 0) 
     return null; 

    Mapper.CreateMap< T, DDLValues>() 
      .ForMember(dest => dest.text, 
         opt => opt.MapFrom(textSelector)) 
      .ForMember(dest => dest.value, 
         opt => opt.MapFrom(valueSelector)); 
    return Mapper.Map<IList<T>, IList<DDLValues>>(objectListToMap); 
} 
+0

Quel superbe effet secondaire: AdmapServ.GetDDLValues ​​ (ContactRepo.GetIt(), p => p.custid.ToString(), p => p.compagnie); Je peux convertir le int ToString() dans le delgate! Réponse fantastique! –

2

Pour construire une requête dynamique de la chaîne:

public class Product 
{ 
    public long ID { get; set; } 
    public string Name { get; set; } 
    public DateTime Date { get; set; } 
} 


static void Main(string[] args) 
{ 
    List<Product> products = (from i in Enumerable.Range(1, 10) 
          select new Product { ID = i, Name = "product " + i, Date = DateTime.Now.AddDays(-i) }).ToList(); //the test case 

    const string SortBy = "Date"; // to test you can change to "ID"/"Name" 

    Type sortType = typeof(Product).GetProperty(SortBy).PropertyType;  // DateTime 
    ParameterExpression sortParamExp = Expression.Parameter(typeof(Product), "p"); // {p} 
    Expression sortBodyExp = Expression.PropertyOrField(sortParamExp, SortBy); // {p.DateTime} 
    LambdaExpression sortExp = Expression.Lambda(sortBodyExp, sortParamExp); // {p=>p.DateTime} 
    var OrderByMethod = typeof(Enumerable).GetMethods().Where(m => m.Name.Equals("OrderBy") && m.GetParameters().Count() == 2).FirstOrDefault().MakeGenericMethod(typeof(Product), sortType); 
    var result = OrderByMethod.Invoke(products, new object[] { products, sortExp.Compile() }); 
} 
1

Si DDLValues a un constructeur qui prend les propriétés de texte et de valeur, il devrait être relativement simple.

IList<DDLValues> GetDDLValues<T>(IList<T> source, Func<T,DDLValues> selector) 
    where T : class 
{ 
    return source.Select(selector) 
       .ToList(); 
} 

Appelé

var ddlList = GetDDLValues(contacts, p => new DDLValues(c.Name, p.ContactID.ToString())); 

Cela suppose que DDLValues ​​a un constructeur comme:

public DDLValues(string text, string value) { ... } 

Si vous tirez de la base de données dans votre source, vous devrez peut-être matérialisez la requête en utilisant ToList() avant d'appliquer le sélecteur pour vous assurer qu'il ne tente pas de convertir le sélecteur en une expression SQL.