创建仅在运行时已知的类型的变量(C#)

创建仅在运行时已知的类型的变量(C#),c#,generics,dynamic,reflection,C#,Generics,Dynamic,Reflection,我的问题非常类似于:,但是这个问题并没有得到真正的回答(也是用C而不是C) 我正在写一些东西来控制一些硬件,根据给定的硬件配置,我必须使用“byte”或“UInt32”类型进行一些位运算。位算术代码很长,但在32位和8位的情况下是相同的,唯一的区别是某些循环的长度(32或8) 我目前的解决方案是使用一个开关,这意味着在一个巨大的if语句中几乎有两个相同代码的副本 另一种解决方案是使用数组或0和1而不是UInt32或字节来执行逐位操作,然后在最后转换为UInt32或字节 最后一个解决方案,我在这里

我的问题非常类似于:,但是这个问题并没有得到真正的回答(也是用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

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

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


您可以在运行时使用以下类似方法创建类型的实例:

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

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.

您可以考虑使用A来实现这一点。您可以从字节或uTI32初始化它,执行按位操作,然后在结束时将其转换为“

”。
    object value;
    bool isByte = value is byte;
    BitArray ba = isByte
        ? new BitArray(new byte[] { (byte)value })
        : new BitArray(BitConverter.GetBytes((unint32)value));
   ...

我可能会创建一个抽象类,类似于
HardwareConfigBase
,它包括循环代码和循环大小。然后有两个子类扩展该基类

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();
}
公共抽象类HardwareConfigBase
{
受保护的int TimesToLoop;
公共字节[]数据=新字节[32*8];//UInt的大小,但仍适用于8位字节
公共无效代码
{
for(int i=0;i
答案相当简单。为了能够在运行时修改uint或字节类型,您不需要在运行时强制转换或转换任何变量。以下三个定义就足够了

第一个类定义是Provider类,它定义了两个方法,每个方法修改uint或byte类型的变量。确保将修改逻辑放在方法中

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 });
    }
}
最后一个定义就是简单地测试这个设置是如何工作的。您可以看到,我们有一个字节和一个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();
    }
}

-1:
myType
的类型已经知道:它是
type
。没有问题。一旦你创造了价值,你将如何处理它?你打算如何对它进行艺术运算?你打算对某个变量做什么?因为直到运行时才知道它是什么类型,所以您将很难针对它编写代码。你需要对它做什么的细节将决定如何让类型系统很好地运行……如果唯一的区别是循环的数量,为什么不去弄清楚呢?对于(inti=0;i<(字节配置?8:32);i++)?
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 });
    }
}
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();
    }
}