2009-09-23 28 views
6

Bu, muhtemelen başka yerler için de geçerlidir, ancak WinForms'de, bağlayıcı kullandığımda, özellik adını vermek için birçok yöntem bulmak istiyorum. gibi bir şey:C# ciltleme işlemini statik olarak yapmanın bir yolu var mı?

class Person 
{ 
    public String Name { get { ... } set { ... } } 
    public int Age { get { ... } set { ... } } 
} 

class PersonView 
{ 
    void Bind(Person p) 
    { 
     nameControl.Bind(p,"Name"); 
     ageControl.Bind(p,"Age"); 
    } 
} 

Bununla zorunda tutun büyük bir sorun "Ad" ve "Yaş" dizeleri olarak belirtilmiş olmasıdır. Bu, kişinin Kişinin özelliklerinden birini yeniden adlandırması durumunda derleyicinin yardımı olmadığı anlamına gelir. Kod iyi bir şekilde derlenecek, ancak bağlamalar bozulacak.

Bunu özlemiş olmanın standart bir yolu var mı? Bazı tip anahtar kelimelere ihtiyacım var gibi geliyor, varolan typeof ile eşleştirmek için stringof denir. Kendini o kadar ayrıştırmak böylece yolu veya dize tam yolunu, bir kısmını almak için özelliklere sahip bazı sınıf geri dönebilirler

ageControl.Bind(p,stringof(p.Age).Name); 

stringof: Bunu gibi bir şey kullanabilirsiniz.

Böyle bir şey zaten yapılabilir mi? Sen, (ya da bir şey bulamazsa için aynı isim bulmak için olduğunu düşünüyorum bu ismi kullanmayı tercih ediyorum döngüsel bir başvuru olacağını ismini ;-)

Elbette bu bulmak için yansıma kullanabilirsiniz

+1

Bu o kadar dinamik bağlar C# bu, değil Örneğin, mevcut projelerin birinde böyle bağlamaları kurmak WinForms. –

+0

Doğru. WinForms kullanmıyor olsanız bile bu tür bir dil özelliği kullanışlı olabilir. –

cevap

2

olarak açıklanabilir bunu yapabilir derleyici tarafından kontrol edilen bağlamalar.

bu tarzı destekleyen
DataBinder 
    .BindToObject(this) 
    .ObjectProperty(c => c.IsReadOnly) 
     .Control(nameTextBox, n => n.ReadOnly) 
     .Control(addressControl, n => n.ReadOnly) 

Kod birkaç sınıfa ayrılır:

public static class DataBinder 
{ 
    public static DataBinderBindingSourceContext<TDataSource> BindToObject<TDataSource>(TDataSource dataSource) 
    { 
     return new DataBinderBindingSourceContext<TDataSource>(dataSource); 
    } 
} 

public class DataBinderBindingSourceContext<TDataSource> 
{ 
    public readonly object DataSource; 

    public DataBinderBindingSourceContext(object dataSource) 
    { 
     DataSource = dataSource; 
    } 

    public DataBinderControlContext<TDataSource, TProperty> ObjectProperty<TProperty>(Expression<Func<TDataSource, TProperty>> property) 
    { 
     return new DataBinderControlContext<TDataSource, TProperty>(this, property); 
    } 
} 

public class DataBinderControlContext<TDataSource, TProperty> 
{ 
    readonly DataBinderBindingSourceContext<TDataSource> BindingSourceContext; 
    readonly string ObjectProperty; 

    public DataBinderControlContext 
     (
      DataBinderBindingSourceContext<TDataSource> bindingSourceContext, 
      Expression<Func<TDataSource, TProperty>> objectProperty 
     ) 
    { 
     BindingSourceContext = RequireArg.NotNull(bindingSourceContext); 
     ObjectProperty = ExpressionHelper.GetPropertyName(objectProperty); 
    } 

    public DataBinderControlContext<TDataSource, TProperty> Control<TControl>(TControl control, Expression<Func<TControl, TProperty>> property) 
     where TControl : Control 
    { 
     var controlPropertyName = ExpressionHelper.GetPropertyName(property); 
     control.DataBindings.Add(controlPropertyName, BindingSourceContext.DataSource, ObjectProperty, true); 

     return this; 
    } 
} 

public static class ExpressionHelper 
{ 
    public static string GetPropertyName<TResult>(Expression<Func<TResult>> property) 
    { 
     return GetMemberNames(((LambdaExpression)property).Body).Skip(1).Join("."); 
    } 

    public static string GetPropertyName<T, TResult>(Expression<Func<T, TResult>> property) 
    { 
     return GetMemberNames(((LambdaExpression)property).Body).Join("."); 
    } 

    static IEnumerable<string> GetMemberNames(Expression expression) 
    { 
     if (expression is ConstantExpression || expression is ParameterExpression) 
      yield break; 

     var memberExpression = (MemberExpression)expression; 

     foreach (var memberName in GetMemberNames(memberExpression.Expression)) 
      yield return memberName; 

     yield return memberExpression.Member.Name; 
    } 
} 

public static class StringExtentions 
{ 
    public static string Join(this IEnumerable<string> values, string separator) 
    { 
     if (values == null) 
      return null; 

     return string.Join(separator, values.ToArray()); 
    } 
} 
0

, özelliği yeniden adlandırıldı ... Ama bir fikir (ya da daha doğrusu, bir hile) var: kullanmak istediğiniz mülke hiçbir şey yapma referansı yaparak, hala orada olduğunu derleme zaman teyidi alırsınız. Sorun sadece birisi çeşitli özellik adlarını değiştirirse, bu durumda, adlar hala var (derleme zamanı hatası yok), ancak farklı uygulama düzeyi anlambilimine sahipler (uygulamanın çıktısında olası sürprizler)

4

bu code snippet Başka bir soru gönderdim, size yardımcı olabilir! (Ama sadece, .NET 3.5 kullanıyorsanız)

Saygılarımızla
Oliver Hanappi

4

Sen ifade ağaçları ile Sen almak için İfadeler kullanabilirsiniz in this question

protected static string GetPropertyName<TSource, TResult>(Expression<Func<TSource, TResult>> expression) 
{ 
    if (expression.NodeType == ExpressionType.Lambda && expression.Body.NodeType == ExpressionType.MemberAccess) 
    { 
     PropertyInfo prop = (expression.Body as MemberExpression).Member as PropertyInfo; 
     if (prop != null) 
     { 
      return prop.Name; 
     } 
    } 
    throw new ArgumentException("expression", "Not a property expression"); 
} 

... 

ageControl.Bind(p, GetPropertyName((Person p) => p.Age)); 
İlgili konular