Static Reflection的飞行场?

时间:2009-04-17 19:26:45

标签: c# reflection static-reflection

我一直在研究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;
        }
    }
}

当然有效并且列出属性相同的次数,但感觉更单一,更不灵活。看起来我应该能够在这里做一些匿名类型的事情吗?

3 个答案:

答案 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 }
};