teemteem
teemteem

Reputation: 21

Create a variable of a type only known at runtime (C#)

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

Answers (5)

Mario Stopfer
Mario Stopfer

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

qJake
qJake

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

Dave Zych
Dave Zych

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

Lee
Lee

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

Porkbutts
Porkbutts

Reputation: 964

Try using the dynamic keyword in C#.

dynamic myType;
if (a) {
    myType = new type1();
} else {
    myType = new type2();
}

Upvotes: -1

Related Questions