2016-11-21 9 views
-1

下限と上限を持つ単純な汎用Rangeを作成したいとします。私は今、クエリパラメータジェネリック型を文字列と逆に変換する

HTTPとしての私のAPI-enpointに新しいDateTimeRangeにパスを作成することができます私のコードではDateTime

public class DateTimeRange : Range<DateTime> 
{ 
    public override string ValueToString(DateTime value) => value.ToString("O"); 
    public override DateTime StringToValue(string source) => DateTime.Parse(source); 
} 

のための実装例では

public abstract class Range<T> 
{ 
    Range(T lower, T upper){/* init _lowerValue and _upperValue (both of type T) */} 

    // this method I would use inside TypeConverter... 
    public static Range<T> Parse(string source){/* build a new instance from string, but how? */} 

    public LowerString => ValueToString(_lowerValue); 
    public UpperString => ValueToString(_upperValue); 

    public abstract string ValueToString(T value); // must be overridden 
    public abstract T StringToValue(string source); // must be overridden 

    public string AsString => $"{LowerString},{UpperString}"; // gets the string-representation of the object 
} 

: /.../api/EndPoint?range=2016-10-21T18:08:03.6190988Z,2016-11-21T18:08:03.6190988Z

しかし、私はこれをapi側でどのように変換できますか?そこで私は私のcontollerアクションに

を文字列2016-10-21T18:08:03.6190988Z,2016-11-21T18:08:03.6190988Zを持っているとタイプを知っているEndpointController.Get(DateTimeRange範囲){/ *解析された範囲で何かをする* /}

が、全く分かりませんこれをRange<DateTime>に変換する方法

私はすでにTypeConverterに目を通しましたが、ジェネリック医薬品については有用なものはありません。

ここでタイプコンバータを使用していますか?これを実現する方法は他にもありますか?

+1

理由だけではなく、 'DatTimeRangeのコンストラクタを作成しません'それは'文字列 'を取る? – juharr

+0

どのようにこのクラスを使いたいですか?投稿例... –

+1

次に、範囲の新しい実装ごとに1つのTypeCoverterを作成するか、既存のものを変更する必要がありますか? – KingKerosin

答えて

2

クラスで静的メソッドを実装することはできません。オブジェクトを渡さずに実装されたメソッドにアクセスします。

これはあなたのニーズにフィットすることができます

https://dotnetfiddle.net/l2nOSp

public abstract class Range<T> 
{ 
    internal T Lower { get; set; } 
    internal T Upper { get; set; } 

    internal Range(T lower, T upper) 
    { 
     Lower = lower; 
     Upper = upper; 
    } 

    // this method I would use inside TypeConverter... 
    internal Range(string source) 
    { 
     string[] parts = source.Split(','); 

     if(parts.Length <= 1) 
      throw new ArgumentException(); 

     if(!this.CanConvert(parts[0]) || !this.CanConvert(parts[1])) 
      throw new ArgumentException(); 

     this.Lower = this.StringToValue(parts[0]); 
     this.Upper = this.StringToValue(parts[1]); 
    } 

    public string LowerString { get { return ValueToString(Lower); } } 
    public string UpperString { get { return ValueToString(Upper); } } 

    public abstract string ValueToString(T value); // must be overridden 
    public abstract T StringToValue(string source); // must be overridden 
    internal abstract bool CanConvert(string source); // must be overridden 

    public string AsString { get { return string.Format("{0},{1}", LowerString, UpperString); }}// gets the string-representation of the object 
} 

そしてDateTimeRangeクラス:

public class DateTimeRange : Range<DateTime> 
{ 

    public DateTimeRange(string source) : base(source) 
    { 

    } 

    public DateTimeRange(DateTime lower, DateTime upper):base(lower, upper) 
    { 

    } 

    public override string ValueToString(DateTime value) { return value.ToString("O"); } 
    public override DateTime StringToValue(string source) { return DateTime.Parse(source); } 
    internal override bool CanConvert(string source) { DateTime dt = new DateTime(); return DateTime.TryParse(source, out dt); } 
} 

用途:

Range<DateTime> a = new DateTimeRange(DateTime.Now.AddDays(-20), DateTime.Now); 
Console.WriteLine(a.AsString); 

Range<DateTime> b = new DateTimeRange("2016-11-01T19:38:05.6409410+00:00,2016-11-21T19:38:05.6409410+00:00"); 
Console.WriteLine(b.AsString); 

エンドポイント方法:

public void Get(string range) //EndpointController.Get 
{ 
    Range<DateTime> b = new DateTimeRange(range); 
    //Do what you need with properties: 
    //b.LowerString 
    //b.UpperString 
} 

あなたを助けて幸せ!

+1

ありがとうございます。 2つのこと。コンストラクタ内の仮想メンバーコールはここで大丈夫ですか? 第2の1つ:したがって、再び、新しいRangeConplementsごとに新しいTypeConverterが必要ですか?いいえ。私は期待していた/私のジェネリックな闘争を助けることができる何かを探して... – KingKerosin

+0

どのように変換のターゲットタイプを知ることができますか? –

+0

あなたは何を期待するのか分からない場合、どのようにジェネリックがあなたのシステムになりますか? –

0

あなたはシングルタイプと(しかし、カスタムフォーマッタなし)これを行うことができます。

https://dotnetfiddle.net/nXsI2S

public class Range<T> 
{ 
    internal T Lower { get; set; } 
    internal T Upper { get; set; } 

    private Range() 
    { 
    } 

    internal Range(T lower, T upper) 
    { 
     Lower = lower; 
     Upper = upper; 
    } 

    internal Range(string source) 
    { 
     string[] parts = source.Split(','); 

     if(parts.Length <= 1) 
      throw new ArgumentException(); 

     var tc = TypeDescriptor.GetConverter(typeof(T)); 

     if(!Range<T>.CanConvert(source)) 
      throw new ArgumentException("string in invalid format", "source"); 

     this.Lower = ((T)tc.ConvertFrom(parts[0])); 
     this.Upper = ((T)tc.ConvertFrom(parts[1])); 
    } 

    public static bool CanConvert(string source) 
    { 
     string[] parts = source.Split(','); 

     if(parts.Length <= 1) 
      throw new ArgumentException(); 

     var tc = TypeDescriptor.GetConverter(typeof(T)); 

     if(!tc.CanConvertFrom(typeof(string))) 
      return false; 

     return tc.IsValid(parts[0]) && tc.IsValid(parts[1]); 
    } 

    public static Range<T> Parse(string source) 
    { 
     Range<T> ret = new Range<T>(); 

     string[] parts = source.Split(','); 

     if(parts.Length <= 1) 
      throw new ArgumentException("string in invalid format", "source"); 

     if(!Range<T>.CanConvert(source)) 
      throw new ArgumentException("string in invalid format", "source"); 

     return new Range<T>(source); 
    } 

    public string LowerString { get { return Lower.ToString(); } } 
    public string UpperString { get { return Upper.ToString(); } } 

    public string AsString { get { return string.Format("{0},{1}", LowerString, UpperString); }}// gets the string-representation of the object 
} 

用途:

string range = "2016-10-01T19:38:05.6409410+00:00,2016-11-21T19:38:05.6409410+00:00"; 

if(Range<int>.CanConvert(range)) 
    Console.WriteLine(Range<int>.Parse(range).AsString); 

if(Range<DateTime>.CanConvert(range)) 
    Console.WriteLine(Range<DateTime>.Parse(range).AsString); 
+0

これはあなたが必要とするもののより近くに見えます。 –

関連する問題