C# 转换MyClass<;SomeType>;给我的班级<;其他类型>;

C# 转换MyClass<;SomeType>;给我的班级<;其他类型>;,c#,generics,C#,Generics,使用C#4.0。我想将MyBuffer的实例转换为MyBuffer的实例。转换器必须足够通用,以处理其他基本类型 我希望这个(或等效的解决方案)能起作用。怎么做? var b1 = MyBuffer.Create(new int[100]); var b2 = Convert.ChangeType(b1, typeof(MyBuffer<float>)); var b3 = Convert.ChangeType(b2, typeof(MyBuffer<byte>));

使用C#4.0。我想将
MyBuffer
的实例转换为
MyBuffer
的实例。转换器必须足够通用,以处理其他基本类型

我希望这个(或等效的解决方案)能起作用。怎么做?

var b1 = MyBuffer.Create(new int[100]);
var b2 = Convert.ChangeType(b1, typeof(MyBuffer<float>));
var b3 = Convert.ChangeType(b2, typeof(MyBuffer<byte>));
在我上面的代码中,有两个主要问题需要解决:

  • 对于任意值
    T
    ,如何确定
    Type
    变量是否等于
    SomeType
  • 是否可以调用
    T
    设置为某个
    Type
    变量的模板函数
  • 由于
    MyBuffer
    包含了一个将缓冲区包装为参数的构造函数,因此非常有用,您只需手动将一个缓冲区转换为另一个缓冲区(使用LINQ非常容易),并创建一个新的“转换”实例:

    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());
    
    更新:

    为了缓解人们对我可能有隐藏意图的担忧,下面是如何通过反思来完成问题所要求的,但更方便的形式是运行时在您的位置进行挖掘:

    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;
    }
    
    很明显,
    字符串
    的行为与字符串数组完全相同。当然,
    动态
    意味着这个特定的数组永远无法与lambdas混合,并且在运行时仍在进行道德上的反射(只有你看不到)。因此,它不是一顿免费的午餐,但有时会被证明是有用的。

    由于
    MyBuffer
    非常有用地包含了一个将缓冲区包装为参数的构造函数,您只需手动将一个缓冲区转换为另一个缓冲区(使用LINQ非常容易),并创建一个新的“转换”实例:

    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());
    
    更新:

    为了缓解人们对我可能有隐藏意图的担忧,下面是如何通过反思来完成问题所要求的,但更方便的形式是运行时在您的位置进行挖掘:

    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;
    }
    
    很明显,
    字符串
    的行为与字符串数组完全相同。当然,
    动态
    意味着这个特定的数组永远无法与lambdas混合,并且在运行时仍在进行道德上的反射(只有你看不到)。因此,这不是一顿免费的午餐,但有时会证明它很有用。

    关于第一个问题:

    if (conversionType.GetGenericTypeDefinition() == typeof(MyBuffer<>))
    
    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);
    }
    
    //您的方法。。。。
    //....
    if(conversionType.IsGenericType&&conversionType.GetGenericArguments().Length>0)
    {//事实上,如果第一个问题解决了,你不需要这个。
    var bufferType=conversionType.GetGenericArguments()[0];
    Func AuxMethod=缓冲转换;
    返回AuxMethod.Method.GetGenericMethodDefinition().MakeGenericMethod(bufferType).Invoke(此为null);
    }
    //……继续你的方法。。。。
    私有MyBuffer BufferConversion()
    {
    NewType[]MyNewArray=Buffer.Select(s=>(NewType)Convert.ChangeType(s,typeof(NewType))).ToArray();
    返回MyBuffer.Create(MyNewArray);
    }
    
    到第一个问题:

    if (conversionType.GetGenericTypeDefinition() == typeof(MyBuffer<>))
    
    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);
    }
    
    //您的方法。。。。
    //....
    if(conversionType.IsGenericType&&conversionType.GetGenericArguments().Length>0)
    {//事实上,如果第一个问题解决了,你不需要这个。
    var bufferType=conversionType.GetGenericArguments()[0];
    Func AuxMethod=缓冲转换;
    返回AuxMethod.Method.GetGenericMethodDefinition().MakeGenericMethod(bufferType).Invoke(此为null);
    }
    //……继续你的方法。。。。
    私有MyBuffer BufferConversion()
    {
    NewType[]MyNewArray=Buffer.Select(s=>(NewType)Convert.ChangeType(s,typeof(NewType))).ToArray();
    返回MyBuffer.Create(MyNewArray);
    }
    
    把这个扔出去。有一个很棒的库,用于转换对象类型,称为AutoMapper


    把这个扔出去。有一个很棒的库,用于转换对象类型,称为AutoMapper


    是的,但我想解决一个更普遍的问题。给定一个
    SomeClass
    实例,如何将其转换为同一类,但使用不同类型的
    T
    ?@l33t由于可能的转换有限,您希望如何解决这两种类型的问题?任何基本类型<代码>字节,
    int
    short
    float
    double
    及其有符号/无符号对应项。也可能是
    bool
    @l33t:假设您有一个方法
    Foo
    ,该方法将
    类型
    作为参数(要转换的缓冲区类型)并神奇地执行您想要的操作(返回转换后的缓冲区)。方法的返回类型是什么?您自己的尝试返回
    对象
    ——您将如何处理此
    对象
    ?我想说的是:一旦你越过这条线进入反射之地,你就再也回不来了。也许用不同的设计能更好地满足您的需求。这个答案很好,除非您有未提及的隐藏意图。是的,但我正在尝试解决一个更普遍的问题。给定一个
    SomeClass
    实例,如何将其转换为同一类,但使用不同类型的
    T
    ?@l33t由于可能的转换有限,您希望如何解决这两种类型的问题?任何基本类型<代码>字节,
    int
    short
    float
    double
    及其有符号/无符号对应项。也可能是
    bool
    @l33t:假设您有一个方法
    Foo
    ,该方法将
    类型
    作为参数(要转换的缓冲区类型)并神奇地执行您想要的操作(返回转换后的缓冲区)。方法的返回类型是什么?您自己的尝试返回
    对象
    ——您将如何使用