简体   繁体   English

静态反射中的动态场?

[英]On-the-fly fields from Static Reflection?

I've been studying up on static reflection with LINQ expressions - very cool! 我一直在研究LINQ表达式的静态反射-太酷了!

One thought I had - is it possible for one class to 'generate' fields on one class based on static reflection done on another class? 我有一个想法-一个类是否可以基于对另一类进行的静态反射来“生成”一个类的字段? I'm thinking specifically of the Builder pattern I've seen here many times. 我在想很多次在这里看到的Builder模式。 I would like to do a fluent-nhibernate-style property registration that 'generates' fields on the builder that match the class I want to build. 我想进行流利的休眠样式属性注册,以“生成”构建器上与我要构建的类匹配的字段。 Soemthing like this: 像这样的东西:

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

and support constructor syntax like this: 并支持如下构造函数语法:

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

The point of all this is to reduce the number of times I have to repeat defining the properies of Color. 所有这些的目的是减少我必须重复定义Color属性的次数。 I played with this: 我玩这个:

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

which certainly works AND lists the properties the same # of times but feels wordier and less flexible. 确实可以正常工作,并且以相同的次数列出了属性,但感觉更加冗长和不灵活。 It seems like I should be able to do something anonymous-type-y here? 看来我应该可以在这里做匿名类型的事?

Worth pointing out that Having a class called Color clashing with the System.Drawing.Color is probably a bad idea. 值得指出的是,拥有一个名为Color的类与System.Drawing.Color冲突可能是一个坏主意。

It is very likely to lead to confusion in others (worse still System.Drawring.Color has value semantics whereas your class has reference semantics which can lead to further confusion) 可能导致其他方面的混乱(更糟糕的是System.Drawring.Color具有值语义,而您的类具有引用语义可能会导致进一步的混乱)

I would point out that what you really want is Named Optional Arguments . 我要指出的是,您真正想要的是“ 命名可选参数” I would suggest that putting in cumbersome Builder classes now will be more effort and made it more painful to move to these once you get to c# 4.0. 我建议现在放入繁琐的Builder类会更加费劲,一旦进入c#4.0,就更难转移到这些类了。 Instead make the constructors that are required (or if need be to avoid type signature collisions static factory methods on the class) 而是使所需的构造函数成为可能(或如果需要避免类签名冲突的静态工厂方法在类上)

I think it's impossible, you can't generate members except by declaring them explicitly. 我认为这是不可能的,除非明确声明成员,否则您无法生成成员。 Bite the bullet and declare a constructor for Color . 咬紧牙关,为Color声明一个构造函数。

PS: I think static reflection is a misnomer, the only thing that's static is the lookup of the member you want to reference — a good thing as far as it goes, but that's not very far. PS:我认为静态反射是用词不当,唯一静态的是您要引用的成员的查找-尽其所能,但这还不是很远。

less code to write but using reflection to set the values. 编写的代码更少,但是使用反射来设置值。

The trick is to use collection initializers. 诀窍是使用集合初始化程序。 it is typesafe. 它是类型安全的。

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

and call syntax 并调用语法

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM