使用C#4.0。我想将MyBuffer<int>
的实例转换为MyBuffer<float>
的实例。转换器必须足够通用以处理其他基本类型。
我想要这个(或等效的解决方案)工作。 HOW吗
var b1 = MyBuffer.Create(new int[100]);
var b2 = Convert.ChangeType(b1, typeof(MyBuffer<float>));
var b3 = Convert.ChangeType(b2, typeof(MyBuffer<byte>));
考虑MyBuffer
类:
public class MyBuffer
{
public static MyBuffer<T> Create<T>(T[] buffer)
where T : struct, IComparable, IConvertible
{
return new MyBuffer<T>(buffer);
}
}
public class MyBuffer<T> : IConvertible
where T : struct, IComparable, IConvertible
{
public T[] Buffer
{
get;
set;
}
public MyBuffer()
{
}
public MyBuffer(T[] buffer)
{
Buffer = buffer;
}
public object ToType(Type conversionType, IFormatProvider provider)
{
if (conversionType == GetType())
return this;
// First problem: Determine if the type is MyBuffer<>.
// if (conversionType == typeof(MyBuffer<>))
{
if (conversionType.IsGenericType && conversionType.GetGenericArguments().Length > 0)
{
var bufferType = conversionType.GetGenericArguments()[0];
dynamic newBuffer = Buffer.
Select(s => Convert.ChangeType(s, bufferType))
.ToArray();
// Second problem: Our dynamic variable will produce an exception here.
return MyBuffer.Create(newBuffer);
}
}
throw new InvalidCastException();
}
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
//
// For completeness...
//
public TypeCode GetTypeCode()
{
throw new NotImplementedException();
}
public bool ToBoolean(IFormatProvider provider)
{
throw new NotImplementedException();
}
public byte ToByte(IFormatProvider provider)
{
throw new NotImplementedException();
}
public char ToChar(IFormatProvider provider)
{
throw new NotImplementedException();
}
public DateTime ToDateTime(IFormatProvider provider)
{
throw new NotImplementedException();
}
public decimal ToDecimal(IFormatProvider provider)
{
throw new NotImplementedException();
}
public double ToDouble(IFormatProvider provider)
{
throw new NotImplementedException();
}
public short ToInt16(IFormatProvider provider)
{
throw new NotImplementedException();
}
public int ToInt32(IFormatProvider provider)
{
throw new NotImplementedException();
}
public long ToInt64(IFormatProvider provider)
{
throw new NotImplementedException();
}
public sbyte ToSByte(IFormatProvider provider)
{
throw new NotImplementedException();
}
public float ToSingle(IFormatProvider provider)
{
throw new NotImplementedException();
}
public string ToString(IFormatProvider provider)
{
throw new NotImplementedException();
}
public ushort ToUInt16(IFormatProvider provider)
{
throw new NotImplementedException();
}
public uint ToUInt32(IFormatProvider provider)
{
throw new NotImplementedException();
}
public ulong ToUInt64(IFormatProvider provider)
{
throw new NotImplementedException();
}
}
在上面的代码中,有两个主要问题需要解决:
Type
变量是否等于SomeType<T>
任意值T
?T
设置为某个Type
变量?答案 0 :(得分:4)
由于MyBuffer<T>
非常有用地包含一个构造函数,该构造函数将缓冲区作为参数包装,您可以手动将一个缓冲区转换为另一个缓冲区(使用LINQ非常简单)并创建一个新的&#34;转换后的#34 ;实例:
var b1 = MyBuffer.Create(new int[100]);
var b2 = MyBuffer.Create(b1.Buffer.Select(i => (float)i).ToArray());
// another way to do the same:
var b3 = MyBuffer.Create(b1.Buffer.Select(Convert.ToSingle).ToArray());
<强>更新强>
为了缓解Daniel关于我可能隐藏意图的问题,这里是如何解决问题反映的问题,而是运行时进行挖掘的更方便的形式你的位置:
dynamic ConvertArray<T>(T[] input, Type target) {
var result = Array.CreateInstance(target, input.Length);
for (var i = 0; i < input.Length; ++i)
{
result.SetValue(Convert.ChangeType(input[i], target), i);
}
return result;
}
此方法允许您执行此操作:
var ints = new[] { 1, 2, 3 };
var strings = ConvertArray(ints, typeof(string));
foreach (var s in strings) {
Console.WriteLine("[{0}] {1}", s.GetType(), s + " potato");
}
很明显,strings
的行为与字符串数组完全相同。当然是dynamic
意味着这个特定的阵列永远不会与... lambdas和反思的道德等同物仍然在运行中进行(只有你不会看到它)。所以它不是一个免费的午餐,但它有时可以说是有用的。
答案 1 :(得分:1)
第一个问题:
if (conversionType.GetGenericTypeDefinition() == typeof(MyBuffer<>))
第二个问题:
//your method....
//....
if (conversionType.IsGenericType && conversionType.GetGenericArguments().Length > 0)
{ //in fact you don't need this if in case the first problem is solved.
var bufferType = conversionType.GetGenericArguments()[0];
Func<MyBuffer<object>> AuxMethod = BufferConversion<object>;
return AuxMethod.Method.GetGenericMethodDefinition().MakeGenericMethod(bufferType).Invoke(this, null);
}
//....continue your method....
private MyBuffer<NewType> BufferConversion<NewType>()
{
NewType[] MyNewArray = Buffer.Select(s => (NewType)Convert.ChangeType(s, typeof(NewType))).ToArray();
return MyBuffer.Create(MyNewArray);
}
答案 2 :(得分:1)
把它扔到那里。有一个很棒的库可以转换名为AutoMapper的对象类型。