Reputation: 21
My question is very similar to : Cast to type known only at runtime , however that one was not really answered (it's also in C rather than C#).
I'm writing something to control some hardware, and depending on the given hardware configuration I have to do some bitwise arithmetic with a "byte" or "UInt32" type. The bit arithmetic code is long but identical in the 32bit and 8bit case, with the only difference being the length of certain loops (32 or 8).
My current solution is to use a switch, which means I have pretty much two copies of the same code in a giant if statement.
An alternative solution is to use an array or 0s and 1s rather than a UInt32 or byte to do the bitwise operations and then convert to UInt32 or byte at the end.
The last solution, which I'm most interested in here, is to dynamically pick which type I will use at runtime. Here is some pseudocode for what I would like:
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
I've searched around to know that the answer may have something to do with generics and reflection, but I can't figure out how to do it exactly.
Upvotes: 2
Views: 1264
Reputation: 551
The answer is rather pretty simple. You will not need to cast or convert any variables at runtime in order to be able to modify uint or byte types at runtime. The following three definitions will suffice.
The first class definition is the Provider class which defines two methods, each one to modify either a variable of uint or byte type. Be sure to put your modifying logic inside the methods.
class Provider
{
public uint GetResult(uint c)
{
return c;
}
public byte GetResult(byte c)
{
return c;
}
}
The next class is the one that will invoke the appropriate method from the previous class definition, depending on the type of the parameter you provide.
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 });
}
}
The last definition is here to simply test how this setup works. You can see that we have both a byte and a uint type. Passing them both to the GetResult(object) method yields the expected results, and as you can see, the underlying system type is also as expected.
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();
}
}
Upvotes: 0
Reputation: 17139
You can create an instance of a type at runtime using Activator.CreateInstance()
like so:
object myInstance = Activator.CreateInstance(MyType);
Then, see this question for how to do a type cast at runtime using only runtime-known types.
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.
Upvotes: 0
Reputation: 21897
I would probably create an abstract class, something like HardwareConfigBase
which includes your looping code as well as the size of the loop. Then have 2 child classes that extend that base class.
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();
}
Upvotes: 1
Reputation: 144206
You might consider using a BitArray for this - you can initialise it from a byte or uint32, do the bitwise operations, and then convert it back at the end e.g.
object value;
bool isByte = value is byte;
BitArray ba = isByte
? new BitArray(new byte[] { (byte)value })
: new BitArray(BitConverter.GetBytes((unint32)value));
...
Upvotes: 1
Reputation: 964
Try using the dynamic
keyword in C#.
dynamic myType;
if (a) {
myType = new type1();
} else {
myType = new type2();
}
Upvotes: -1