2

我的问题非常类似于:Cast to type known only at runtime,但是没有真正回答这个问题(它也在 C 而不是 C# 中)。

我正在编写一些东西来控制一些硬件,并且根据给定的硬件配置,我必须使用“byte”或“UInt32”类型进行一些按位运算。位算术代码很长,但在 32 位和 8 位情况下是相同的,唯一的区别是某些循环的长度(32 或 8)。

我目前的解决方案是使用一个开关,这意味着我在一个巨大的 if 语句中有几乎两个相同代码的副本。

另一种解决方案是使用数组或 0 和 1 而不是 UInt32 或字节来执行按位运算,然后在最后转换为 UInt32 或字节。

我在这里最感兴趣的最后一个解决方案是动态选择我将在运行时使用的类型。这是我想要的一些伪代码:

System.Type MyType;    
if (something)
    MyType=type1;
else
    MyType=somethingElse;

myType someVariable; //Create a variable of type myType. This line will give an 
                     //error
someVariable=(myType) otherVariable //do an example typecast with the 
                                    //runtime-determined type

我四处搜索知道答案可能与泛型和反射有关,但我无法弄清楚如何准确地做到这一点。

4

5 回答 5

1

您可能会考虑为此使用BitArray - 您可以从字节或 uint32 初始化它,执行按位运算,然后在最后将其转换回来,例如

    object value;
    bool isByte = value is byte;
    BitArray ba = isByte
        ? new BitArray(new byte[] { (byte)value })
        : new BitArray(BitConverter.GetBytes((unint32)value));
   ...
于 2013-05-23T20:16:11.703 回答
1

我可能会创建一个抽象类,HardwareConfigBase其中包括您的循环代码以及循环的大小。然后有 2 个扩展该基类的子类。

public abstract class HardwareConfigBase
{
    protected int TimesToLoop;
    public byte[] Data = new byte[32 * 8]; //Size of UInt, but still works for 8bit byte

    public void MyLoopCode
    {
        for(int i = 0; i < TimesToLoop; i++)
        {
            //Do whatever
        }
    }
}

public class ByteHardwareConfig
{
    public ByteHardwareConfig
    {
        TimesToLoop = 8;
    }
}

public class UIntHardwareConfig
{
    public UIntHardwareConfig
    {
         TimesToLoop = 32;
    }
}

public void Main()
{
    var myHardwareConfig = new ByteHardwareConfig(); //Could also be UInt
    //Do some more initialization and fill the Data property.
    myHardwareConfig.MyLoopCode();
}
于 2013-05-23T20:21:13.497 回答
0

Activator.CreateInstance()您可以像这样在运行时创建一个类型的实例:

object myInstance = Activator.CreateInstance(MyType);

然后,请参阅此问题,了解如何在运行时仅使用运行时已知的类型进行类型转换。

public static dynamic Convert(dynamic source, Type dest) {
    return Convert.ChangeType(source, dest);
}

myInstance = Convert(myInstance, MyType);
// will result in myInstance being of type MyType.
于 2013-05-23T20:16:03.120 回答
0

答案相当简单。您无需在运行时强制转换或转换任何变量,以便能够在运行时修改uintbyte类型。以下三个定义就足够了。

第一个类定义是Provider类,它定义了两个方法,每个方法修改一个uintbyte类型的变量。请务必将您的修改逻辑放在方法中。

class Provider
{
    public uint GetResult(uint c)
    {
        return c;
    }

    public byte GetResult(byte c)
    {
        return c;
    }
}

下一个类将从上一个类定义中调用适当的方法,具体取决于您提供的参数的类型。

class Execute
{
    public object GetResult(object source)
    {
        var provider = new Provider();

        return provider.GetType()
                       .GetMethods()
                       .Where(x => x.Name == "GetResult" && x.ReturnType == source.GetType())
                       .First()
                       .Invoke(provider, new object[] { source });
    }
}

最后一个定义是为了简单地测试这个设置是如何工作的。你可以看到我们有一个byte和一个uint类型。将它们都传递给GetResult(object)方法会产生预期的结果,并且如您所见,底层系统类型也符合预期。

class Program
{
    static void Main()
    {
        uint u = 1;
        byte b = 2;

        var result1 = new Execute().GetResult(u);
        var result2 = new Execute().GetResult(b);

        sc.WriteLine(result1 + " " + result1.GetType().UnderlyingSystemType);
        sc.WriteLine(result2 + " " + result2.GetType().UnderlyingSystemType);

        sc.Read();
    }
}
于 2013-06-03T19:37:39.447 回答
-1

尝试dynamic在 C# 中使用关键字。

dynamic myType;
if (a) {
    myType = new type1();
} else {
    myType = new type2();
}
于 2013-05-23T20:13:22.830 回答