C# 将泛型类型转换为字符串并返回
我想建立一个简单的通用范围,它有一个下限和一个上限C# 将泛型类型转换为字符串并返回,c#,generics,type-conversion,C#,Generics,Type Conversion,我想建立一个简单的通用范围,它有一个下限和一个上限 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(stri
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
}
在我的代码中,我现在可以创建一个新的DateTimeRange,并将其作为查询参数传递给我的api enpoint
http:/…/api/EndPoint?range=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.GetDateTimeRange范围{/*对解析的范围*/}
但不知道如何将其转换回范围
我已经研究了TypeConverter,但没有发现任何关于泛型的有用信息
在这里使用类型转换器是正确的方法吗?或者在如何实现这一点上还有其他最佳实践吗?如果不传递对象,就无法在访问已实现方法的范围类上实现静态方法 这可能适合您的需要: 然后是DateTimeRange类: 用法: 端点方法:
很高兴帮助你 您可以使用单一类型但不使用自定义格式化程序来执行此操作: 用法:
为什么不在DatTimeRange上创建一个带字符串的构造函数呢?您想如何使用这些类?发布一个示例…然后我需要为Range的每个新实现创建一个TypeCoverter,或者更改现有的一个,否?您有两个值作为一个范围,并且希望转换为单个值??。。如何选择小写字符串还是大写字符串?@IgorQuirino是的,主要是我想要的。谢谢。两件事。这里的虚拟成员调用构造函数是否正常?第二个:因此,对于每个新的范围实现,我确实需要一个新的TypeConverter,不是吗?。我希望/寻找一些东西,可以帮助我在转换回时的一般斗争…如何知道转换的目标类型?我认为.NET正在寻找一个类型转换器,而实际使用的参数是类型x。因此,对于GetDateTimeRange范围,范围的类型由ModelBuilder/TypeConverter知道。我实际上就是这么做的。我想到了比每次用字符串调用ctor更简单的方法。最后我写了一篇关于类型转换器的文章。但是我每个实现有一个类型转换器。所以你的解决方案很好。也许是我对魔法的期望太高了。这看起来更接近你的需要。
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>
{
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
}
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
}
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);