【问题标题】:On-the-fly fields from Static Reflection?静态反射的动态场?
【发布时间】:2010-10-20 04:43:22
【问题描述】:

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

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

【问题讨论】:

    标签: c# reflection static-reflection


    【解决方案1】:

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

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

    【讨论】:

    • 感谢您的回答。我有一个颜色的构造函数,但这意味着再次列出参数。您是否发现构建器“通过”颜色存在问题?
    • 我没有看到问题(除非打开了迂腐模式 :),但 看不出拥有构建器的意义。
    【解决方案2】:

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

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

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

    【讨论】:

    • 优秀的分数。就我而言,我真的在尝试模拟“零件和汽车可以使用的颜色”。也许我应该跟随我们英国同事的领导,名字是 Color ;)
    • 我建议使用 PartColor 作为名称,如果它是不可变的且很小,您可能需要考虑将其设为结构,但只要它是不可变的,就足以避免出现问题。我是英国人,但在拼写编程术语时是一个归化的 Yank。颜色,同步等 :)
    【解决方案3】:

    要编写的代码更少,但使用反射来设置值。

    诀窍是使用集合初始化器。它是类型安全的。

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-08-11
      • 2012-03-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-10-28
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多