我一直在研究LINQ表达式的静态反射 - 非常酷!
我有一个想法 - 一个类是否有可能基于另一个类上的静态反射在一个类上“生成”字段?我正在考虑我多次见过的Builder模式。我想做一个流畅的nhibernate风格的属性注册,在构建器上“生成”与我想要构建的类匹配的字段。像这样的东西:
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();
所有这一切的要点是减少重复定义Color属性的次数。我玩过这个:
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;
}
}
}
当然有效并且列出属性相同的次数,但感觉更单一,更不灵活。看起来我应该能够在这里做一些匿名类型的事情吗?
答案 0 :(得分:1)
值得指出的是,让一个名为Color的类与System.Drawing.Color发生冲突可能是一个坏主意。
非常可能会导致其他人混淆(更糟糕的是,System.Drawring.Color仍然具有值语义,而您的类具有可能导致进一步混淆的引用语义)
我想指出你真正想要的是Named Optional Arguments。我建议现在加入繁琐的Builder类会更加努力,一旦你进入c#4.0,就会更加痛苦。而是制作所需的构造函数(或者如果需要,则避免类型签名冲突类上的静态工厂方法)
答案 1 :(得分:0)
我认为这是不可能的,除非明确声明成员,否则无法生成成员。咬紧牙关并声明Color
的构造函数。
PS:我认为静态反射是一种误称,唯一不变的就是查找你想要引用的成员 - 这是一件好事,但事实并非如此。
答案 2 :(得分: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 }
};