我想构建一个具有下限和上限的简单泛型Range
。
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
}
使用DateTime
public class DateTimeRange : Range<DateTime>
{
public override string ValueToString(DateTime value) => value.ToString("O");
public override DateTime StringToValue(string source) => DateTime.Parse(source);
}
在我的代码中,我现在可以创建一个新的DateTimeRange,并将其传递给我的api-enpoint作为query-parameter
HTTP:/.../ API /端点范围= 2016-10-21T18:08:03.6190988Z,2016-11-21T18:08:03.6190988Z
但是如何在api端转换回来呢?在那里我只有字符串2016-10-21T18:08:03.6190988Z,2016-11-21T18:08:03.6190988Z
并知道我的控制器 - 动作
EndpointController.Get(DateTimeRange range){/ *用解析的范围执行某些操作* /}
但不知道如何将其转换回Range<DateTime>
。
我已经调查了TypeConverter
,但没有找到有关仿制药的任何有用信息。
在这里使用类型转换器是正确的方法还是有关于如何实现这一目标的其他最佳实践?
答案 0 :(得分: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 :(得分: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);