2009-04-17 38 views
2

我一直在研究LINQ表達式的靜態反射 - 非常酷!來自靜態反射的動態字段?

我以爲有一個想法 - 一個類是否有可能根據另一個類上的靜態反射在一個類上「生成」字段?我特意想到了我在這裏看到的Builder模式很多次。我想做一個流利的nhibernate風格的屬性註冊,在構建器上生成與我想構建的類相匹配的字段。 Soemthing像這樣:像這樣

public class Color 
{ 
    private Color() 
    { 
    } 
    public string Name { get; private set; } 

    public class Builder : BuilderBase<Color> 
    { 
     public Builder() 
     { 
      Property(x => x.Name); 
     } 
     public Build() 
     { 
      return built_up_color; 
     } 
    } 
} 

和支持的構造函數語法:

Color c = new Color.Builder() { Name = "Red" }.Build(); 

所有這一切的關鍵是減少我要重複定義顏色的性的判定的次數。我玩這個:

public class Color 
{ 
    private Color() 
    { 
    } 
    public string Name { get; private set; } 

    public class Builder 
    { 
     private Color _color = new Color(); 
     public string Name 
     { 
      get { return _color.Name; } 
      set { _color.Name = value; } 
     } 

     public Build() 
     { 
      return _color; 
     } 
    } 
} 

這當然可以工作,並列出屬性相同的次數,但感覺更加靈活和不太靈活。似乎我應該可以在這裏做一些匿名類型的東西?

回答

1

值得指出的是,有一個名爲Color與Class.Drawing.Color相沖突的類可能是一個壞主意。

這是非常可能導致他人混亂(更糟糕的是System.Drawring.Color值語義的,而你的類有引用語義這可能會導致進一步的混亂)

我要指出的是什麼你真的想要的是Named Optional Arguments。我建議現在加入繁瑣的Builder類將會更加努力,並且一旦到達C#4.0就會更加痛苦。取而代之的是構造函數是必需的(或者如果需要避免類型簽名衝突靜態工廠方法)

0

我認爲這是不可能的,你不能生成成員,除非明確聲明它們。咬住項目符號併爲Color聲明構造函數。 PS:我認爲靜態反射是一個誤稱,唯一靜態的是你想要引用的成員的查找 - 儘管它是一個好東西,但那不是很遠。

+0

謝謝您的回答。我有一個顏色的構造函數,但它意味着再次參數化參數。您是否看到建造商「通過」顏色的問題? – n8wrl 2009-04-17 20:15:06

+0

我沒有看到問題(除非迂腐模式:),但*我*沒有看到建設者的觀點。 – 2009-04-18 06:41:34

0

減少代碼編寫但使用反射來設置值。

訣竅是使用集合初始值設定項。它是類型安全的。

public class Color 
{ 
    private Color() 
    { 
    } 
    public string Name { get; private set; } 
    public int Prop2 { get; private set; } 

    public class Builder : Builder<Color> 
    { 
     public Builder() 
     { 
      // possible 
      _instance.Name = "SomeDefaultValue"; 
     } 
    } 
} 

class Builder<T> : IEnumerable<string> 
{ 
    protected T _instance = Activator.CreateInstance(typeof(T)); 

    public void Add<TProperty>(Expression<Func<T, TProperty>> prop, TProperty value) 
    { 
     StaticReflection.GetPropertyInfo(prop).SetValue(_instance, value, null); 
    } 

    public static implicit operator T(Builder<T> builder) 
    { 
     return builder.Build(); 
    } 

    public T Build() 
    { 
     return _instance; 
    } 

    IEnumerator<string> IEnumerable<string>.GetEnumerator() 
    { 
     // e.g. return iterator over the property names 
     throw new NotImplementedException(); 
    } 

    IEnumerator IEnumerable.GetEnumerator() 
    { 
     return ((IEnumerable<string>)this).GetEnumerator(); 
    } 
} 

,並調用語法

var color = new Color.Builder 
{ 
    { x => x.Name, "foo" }, 
    { x => x.Prop2, 5 } 
}.Build(); 

// or 

var color = new Builder<Color> 
{ 
    { x => x.Name, "foo" }, 
    { x => x.Prop2, 5 } 
}.Build(); 

// or 

Color color = new Builder<Color> 
{ 
    { x => x.Name, "foo" }, 
    { x => x.Prop2, 5 } 
};