2

我一直在研究使用 LINQ 表达式的静态反射——非常酷!

我有一个想法——一个类是否有可能基于对另一类进行的静态反射在一个类上“生成”字段?我特别想到了我在这里多次看到的 Builder 模式。我想做一个 fluent-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();

这一切的目的是减少我必须重复定义颜色属性的次数。我玩这个:

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

这当然有效,并且列出了相同的属性 # 次,但感觉更冗长且不太灵活。看来我应该可以在这里做一些匿名类型的事情?

4

3 回答 3

1

值得指出的是,让一个名为 Color 的类与 System.Drawing.Color 发生冲突可能是个坏主意。

可能导致其他人混淆(更糟糕的是 System.Drawring.Color 具有值语义,而您的类具有引用语义,这可能导致进一步的混淆)

我会指出,您真正想要的是Named Optional Arguments。我建议现在放入繁琐的 Builder 类将更加努力,并且一旦您进入 c# 4.0 就会更痛苦地迁移到这些类。而是制作所需的构造函数(或者如果需要避免类型签名冲突,则类上的静态工厂方法)

于 2009-04-24T14:12:21.917 回答
0

我认为这是不可能的,除非明确声明它们,否则您无法生成成员。咬紧牙关,为Color.

PS:我认为静态反射是用词不当,唯一静态的就是查找要引用的成员——就它而言,这是一件好事,但这并不是很远。

于 2009-04-17T19:45:17.320 回答
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 }
};
于 2012-02-17T13:32:22.443 回答