我的问题非常类似于:转换为仅在运行时已知的类型,但是这个问题没有得到真正的回答(它也是在C中而不是c#中)。
我正在写一些东西来控制一些硬件,根据给定的硬件配置,我必须用"byte"或"UInt32"类型做一些按位算术。位算术码很长,但在32位和8位的情况下相同,唯一的区别是某些循环的长度(32或8)。
我目前的解决方案是使用一个开关,这意味着我在一个巨大的if语句中有几乎相同代码的两个副本。
另一种解决方案是使用数组或0和1,而不是使用UInt32或byte进行按位操作,然后在最后转换为UInt32或byte。
最后一个解决方案,也是我在这里最感兴趣的,是动态地选择我将在运行时使用的类型。下面是我想要的一些伪代码:
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
我搜索了一下,知道答案可能与泛型和反射有关,但我不知道如何准确地做到这一点。
你可以考虑使用BitArray——你可以从字节或uint32初始化它,进行按位操作,然后在最后将其转换回来,例如
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();
}
您可以在运行时使用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.
答案相当简单。为了能够在运行时修改 int或byte类型,您不需要在运行时强制转换或转换任何变量。以下三个定义就足够了。
第一个类定义是Provider类,它定义了两个方法,每个方法修改 int或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 });
}
}
最后一个定义是为了简单地测试这个设置是如何工作的。您可以看到,我们有一个字节和一个 int类型。将它们都传递给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();
}
}
尝试在c#中使用dynamic
关键字。
dynamic myType;
if (a) {
myType = new type1();
} else {
myType = new type2();
}