2

私は LINQ 式を使用した静的リフレクションについて勉強してきました - とてもクールです!

私が持っていた1つの考え-あるクラスが、別のクラスで行われた静的リフレクションに基づいて、あるクラスでフィールドを「生成」することは可能ですか? ここで何度も見た 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;
        }
    }
}

これは確かに機能し、プロパティを同じ回数リストしますが、冗長で柔軟性が低く感じます。ここで匿名型の何かをすることができるはずですか?

4

3 に答える 3

1

ColorというクラスをSystem.Drawing.Colorと衝突させることはおそらく悪い考えであることを指摘する価値があります。

他の人の混乱につながる可能性が非常に高いです(さらに悪いことに、System.Drawring.Colorには値のセマンティクスがありますが、クラスにはさらに混乱を招く可能性のある参照セマンティクスがあります)

私はあなたが本当に欲しいのはNamedOptionalArgumentsであることを指摘します。面倒なBuilderクラスを今すぐ入れるのはもっと手間がかかり、c#4.0に到達したらこれらに移行するのがもっと苦痛になることをお勧めします。代わりに、必要なコンストラクターを作成します(または、型シグネチャの衝突を回避する必要がある場合は、クラスの静的ファクトリメソッド)

于 2009-04-24T14:12:21.917 に答える
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 に答える
0

明示的に宣言しない限り、メンバーを生成することはできません。弾丸をかみ、コンストラクターを宣言しColorます。

PS: 静的なリフレクションは誤称だと思います。静的なのは、参照したいメンバーのルックアップだけです。これは良いことですが、それほど遠くはありません。

于 2009-04-17T19:45:17.320 に答える