0

これが私の状況です: プロパティを再設定するクラスがあります:

public abstract class RootProperty { 
    public int Id {get; set;}
}
public class AProperty {}
public class BProperty {}

そして、これらの戦利品があるようにしましょう:

public class ZProperty {}

そして、この各プロパティの値、

public abstract class RootValue {
    public RootProperty Property {get;set;}
}
public class AValue : RootValue {
    public AValue(AProperty) { ... }
    public string Value {get; set;} 
}
public class ZValue : RootValue {
    public ZValue(ZProperty) { ... }
    public sometipe Value {get;set;} }

実際、各クラスは、物が持たなければならないプロパティのタイプを表しています。したがって、特定のドメインで値が必要な文字列によってプロパティが定義されていると言いたい場合は、次のように言います。

public class DomainProperty {
    public ICollection<string> Domain {get; set;}
}
public class DomainValue {
    public DomainValue(DomainProperty) {...}
    public string Value
    {
        set { 
            if (!this.Property.Domain.Any(d=>d==value)) {
                throw new Exceptin("Value out of range!");
            }
        }
    }
}

だから私は犬が小さくても大きくてもいいし、私の犬は大きい。

DomainProperty DogsSize = new DomainProperty { Domain= ["big","small"] }
DomainValue MyDogSize = new DomainValue(color) { Value = "big" }

これを使用して、最大値と最小値などを含む数値範囲のプロパティを定義できます。最初の質問は次のとおりです。カスタマイズ可能なプロパティの型に関するこの問題の解決策を他に考えられますか?

さて、ここに投稿する質問: 前のロジックはサーバー側にあり、クライアント側から抽象的な dtos のリストを受け取ります。

public abstract class RootDto { public int PropertyId { get; set; } }
public class ADto : RootDto { public string Value { get; set; } }
public class BDto: RootDto { public bool Value { get; set; } }
public class ZDto : RootDto { public someothertype Value { get; set; } }

RootDto PropertyId を使用すると、元の RootProperty を見つけることができます。?Value の新しいインスタンスを作成し、値を ?Dto.Value に設定したいと考えています。今、私は多くのキャストでこれを持っています:

List<RootDto> listDto;
foreach(dto in listDtio) {
    if (someDto is ADto) {
        ADto castedDto = (ADto) dto;
        AProperty dtoProperty = (AProperty) Repository.findRootProperty(dto.PropertyId);
        AValue valueForDto = new AValue(dtoProperty);
        valueForDto.Value = castedDto.Value;
    }
    if ...(B.....Z)
}

それは機能しますが、15 の可能なプロパティ クラスがあるとしたら、反復コードの行が大量になります。リフレクションと動的タイプを調査しましたが、何も見つかりませんでした。お時間をいただきありがとうございます。良い説明ができれば幸いです。

4

2 に答える 2

2

あなたのコードは非常に紛らわしいので、私の回答コードも最善ではありませんが、コードを理解すれば答えを理解できます。

私が試す最初のアプローチはジェネリックです。

最初に、いくつかの抽象値を取得し、ルート クラスに設定します。

public abstract class RootValue 
{
    public RootProperty Property {get;set;}
    public abstract object ValueInRoot {get; set;}
}

public abstract class RootDto 
{ 
    public int PropertyId {get; set; } 
    public abstract object ValueInRoot {get; set; }
}

最後のメソッドで新しい AProperty を作成するので、これも RootProperty を継承していると思います。そのため、RootProperty も上記の考え方に従う必要があります。しかし、Property クラスは不要かもしれないことがわかると思います。(ValueClass のコメントを参照してください) RootProperty にCreateValueメソッドがあったことを示唆しています。

public abstract class RootProperty 
{ 
    public int Id {get; set;}

    public abstract RootValue CreateValue();
}

AProperty から ZProperty がある場合は、このような単一のクラス宣言を使用します。これはジェネリック クラスであり、型パラメーター ( TValue) を取りますが、コンパイル時には不明です。

//I really believe the properties are inheriting RootProperty
public class Property<TValue> : RootProperty
{
    public ValueClass<TValue> CreateTypedValue()
    { 
        //Create the new ValueClass<TValue> here;
        //I believe it's the best place to do that.

        //It will know the type and it can be called via the 
        //overriden method below

        //This way you avoid calling the Value contructor in your 
        //final method.
    }

    public override RootValue CreateValue()
    {
        return this.CreateTypedValue();
    }
}

ZValue を介して AValue がある場合は、これを使用して、そのルート値をオーバーライドします (ここでプロパティを使用する方法がわからないので、コンストラクターのコメントを見てアイデアを確認してください)。

public class ValueClass<TValue> : RootValue 
{
    //this line is not clear for me....
    public ValueClass(Property<TValue>) 
    { 
        //I believe you should leave the task of creating this ValueClass to the 
        //Property CreateTypedValue() method.

        //See that I added the CreateValue in te property classes,
        //you will see further on why I did that. It solves constructor problem.
    }         

    public TValue Value {get; set;}

    public override object ValueInRoot
    {
        get { return Value; }
        set { Value = (TValue)value; }
    }
}

ドメインの場合:

public class DomainProperty<TValue> 
{
    public ICollection<TValue> Domain {get; set;}
}

public class DomainValue<TValue> 
{
   public DomainValue(DomainProperty<TValue>) {...}
   public TValue Value
    {
        set { 
            //Here I'd use Domain.Contains(value)
            if (!this.Property.Domain.Any(d=>d==value)) 
             {
                 throw new Exceptin("Value out of range!");
             }
         }
   }
 }

DTO の場合、ルート値も上書きされます。

public class Dto<TValue> : RootDto 
{
    public TValue Value {get; set;} 
    public override object ValueInRoot
    {
        get { return Value; }
        set { Value = (TValue)value; }
    }
}

そして最後に、サーバー上の割り当てメソッド:

foreach(dto in listDtio) 
{
    //if (someDto is ADto) 
    //{
        //ADto castedDto = (ADto) dto;
        RootProperty dtoProperty = Repository.findRootProperty(dto.PropertyId);

        //here is the way you solve your constructor problem.
        RootValue valueForDto = dtoProperty.CreateValue();

        //and here you assign values without knowing their types,
        //but they will still be typed
        valueForDto.ValueInRoot = dto.ValueInRoot;
    //}
    //if ...(B.....Z)
}
于 2013-06-05T21:39:14.137 に答える
0

手始めに: 考えられる解決策は、RootValue から拡張されたすべてのクラスのコンストラクターで反復処理を行い、XProperty 引数を使用していくつかを見つけ、それを呼び出し、Value を動的に割り当てることです。

于 2013-06-05T20:32:53.677 に答える