80

I'm in a situation where I'd like to instantiate an object of a type that will be determined at runtime. I also need to perform an explicit cast to that type.

Something like this:

static void castTest(myEnum val)
{
    //Call a native function that returns a pointer to a structure
    IntPtr = someNativeFunction(..params..);

    //determine the type of the structure based on the enum value
    Type structType = getTypeFromEnum(val);

    structType myStruct = (structType)Marshal.PtrToStructure(IntPtr, structType);
}

This is obviously not valid code, but I hope it conveys the essence of what I'm trying to do. The method I'm actually working on will have to perform the marshaling operation on ~35 different types. I have several other methods that will need to do something similar with the same set of types. So, I'd like to isolate the type-determining logic from these methods so that I only need to write it once, and so that the methods stay clean and readable.

I must admit to being a total novice at design. Could anyone suggest a good approach to this problem? I suspect there might be an appropriate design pattern that I'm unaware of.

abatishchev
  • 98,240
  • 88
  • 296
  • 433
Odrade
  • 7,409
  • 11
  • 42
  • 65
  • 1
    Maybe http://msdn.microsoft.com/en-us/library/system.activator.aspx can help you? It is often useful for instantiating objects whose type you only know at runtime. It can be done with regular Reflection to but it's a little bit fiddlier. I have no ideas on your design though so I wont make an answer. – Skurmedel Jun 11 '09 at 14:13
  • 1
    possible duplicate of [Get a new object instance from a Type](http://stackoverflow.com/questions/752/get-a-new-object-instance-from-a-type) – nawfal Jun 12 '13 at 20:19

6 Answers6

150

There are several ways you can create an object of a certain type on the fly, one is:

// determine type here
var type = typeof(MyClass);

// create an object of the type
var obj = (MyClass)Activator.CreateInstance(type);

And you'll get an instance of MyClass in obj.

Another way is to use reflection:

// get type information
var type = typeof(MyClass);

// get public constructors
var ctors = type.GetConstructors(BindingFlags.Public);

// invoke the first public constructor with no parameters.
var obj = ctors[0].Invoke(new object[] { });

And from one of ConstructorInfo returned, you can "Invoke()" it with arguments and get back an instance of the class as if you've used a "new" operator.

chakrit
  • 61,017
  • 25
  • 133
  • 162
  • 34
    This doesn't answer the question (entirely). He doesn't know at compile-time if it will be `MyClass` or `HisClass` or `HerClass` (runtime-determined type). – Bitterblue Jun 06 '13 at 10:12
  • 4
    @mini-me Note that in the question the OP included `Type structType = getTypeFromEnum(val);`. I am just adding an example code to demonstrate that one should obtains the `Type` instance first. – chakrit Jun 06 '13 at 10:22
  • 1
    Not sure if you got that: I criticized the cast part of your answer. The answer of Rex M gives a full working solution + references another way using dynamics. – Bitterblue Jun 06 '13 at 11:37
  • 2
    @mini-me It is just an example. The OP is looking for an API to do this. The code is just enough to answer. I can't make everything compile in the way the OP would have wanted and that wouldn't really help the OP. And IMO In reality most of time you will at least know and want the object to be based of some base types or interfaces and almost always never go full dynamic or just plain `Object` directly since those are pretty useless (or would not requires runtime reflection to use.) – chakrit Jun 07 '13 at 17:48
  • 2
    Instead of `typeof(MyClass)` I used `inputObj.GetType()`. This provides the type, but may not work for casting. In my case, I had a suitable parent that was sufficient for casting. – Zarepheth Sep 19 '13 at 17:52
  • This requires knowing what the class type is at the time of compilation, which the OP says they don't know. Rex M's answer is better – John Stock Oct 31 '20 at 00:14
18

You can mostly do what you're describing, but since you don't know the type at compile-time, you'll have to keep the instance loosely-typed; check its type at each point you use it, and cast it appropriately then (this will not be necessary with c# 4.0, which supports dynamics):

Type type = CustomGetTypeMethod();
var obj = Activator.CreateInstance(type);

...


if(obj is MyCustomType)
{
    ((MyCustomType)obj).Property1;
}
else if (obj is MyOtherCustomType)
{
    ((MyOtherCustomType)obj).Property2;
}
Rex M
  • 142,167
  • 33
  • 283
  • 313
11

I think you're looking for Activator.CreateInstance

Restore the Data Dumps
  • 38,967
  • 12
  • 96
  • 122
  • 3
    Yes, I did too. I used this for help. http://stackoverflow.com/questions/752/get-a-new-object-instance-from-a-type-in-c – Valamas Jul 25 '11 at 04:28
6

Creating an instance of a run-time determined Type is easy, using Activator.CreateInstance, as others have mentioned. However, casting it, as you do in your example on the Marshal.PtrToStructure line is not possible, as the type has to be known at compile time for casting. Also, note that Activator.CreateInstance can not be used in conjunction with an IntPtr.

If your types have a common base class (other than Object), you can cast it to said base type and call functions on that. Otherwise, calling functions will only be possible using reflection.

So either:

static void castTest(myEnum val)
{
  //Call a native function that returns a pointer to a structure
  IntPtr val = someNativeFunction(..params..);

  //determine the type of the structure based on the enum value
  Type structType = getTypeFromEnum(val);

  BaseClass myStruct = (BaseClass)Marshal.PtrToStructure(IntPtr, structType);
  myStruct.SomeFunctionDeclaredInBaseClass();
}

Or:

static void castTest(myEnum val)
{
  //Call a native function that returns a pointer to a structure
  IntPtr val = someNativeFunction(..params..);

  //determine the type of the structure based on the enum value
  Type structType = getTypeFromEnum(val);

  object myStruct = Marshal.PtrToStructure(IntPtr, structType);
  MemberInfo[] function = FindMembers(MemberTypes.Method, BindingFlags.Public | BindingFlags.Instance,
    (MemberFilter)delegate(MemberInfo info, object filter)
    {
      return info.Name == filter.ToString();
    }, "SomeFunction");
  if (mi.Length > 0 && mi[0] is MethodInfo)
    ((MethodInfo)mi[0]).Invoke(myStruct, ..params..);
}
Aistina
  • 12,435
  • 13
  • 69
  • 89
  • +1. @Aistina's more useful idea is to define a base class or interface and do whatever work is needed against that rather than just creating an instance of a run-time determined type – Evan May 27 '10 at 19:18
1

You could go dynamic:

using System;

namespace TypeCaster
{
    class Program
    {
        internal static void Main(string[] args)
        {
            Parent p = new Parent() { name = "I am the parent", type = "TypeCaster.ChildA" };
            dynamic a = Convert.ChangeType(new ChildA(p.name), Type.GetType(p.type));
            Console.WriteLine(a.Name);

            p.type = "TypeCaster.ChildB";
            dynamic b = Convert.ChangeType(new ChildB(p.name), Type.GetType(p.type));
            Console.WriteLine(b.Name);
        }
    }

    internal class Parent
    {
        internal string type { get; set; }
        internal string name { get; set; }

        internal Parent() { }
    }

    internal class ChildA : Parent
    {
        internal ChildA(string name)
        {
            base.name = name + " in A";
        }

        public string Name
        {
            get { return base.name; }
        }
    }

    internal class ChildB : Parent
    {
        internal ChildB(string name)
        {
            base.name = name + " in B";
        }

        public string Name
        {
            get { return base.name; }
        }
    }
}
Jakob Flygare
  • 189
  • 1
  • 2
-7
 methodName = NwSheet.Cells[rCnt1, cCnt1 - 2].Value2;
                            Type nameSpace=typeof(ReadExcel);
                            Type metdType = Type.GetType(nameSpace.Namespace + "." + methodName);
                            //ConstructorInfo magicConstructor = metdType.GetConstructor(Type.EmptyTypes);
                            //object magicClassObject = magicConstructor.Invoke(new object[] { });
                            object magicClassObject = Activator.CreateInstance(metdType);
                            MethodInfo mthInfo = metdType.GetMethod("fn_"+methodName);
                            StaticVariable.dtReadData.Clear();
                            for (iCnt = cCnt1 + 4; iCnt <= ShtRange.Columns.Count; iCnt++)
                            {
                                temp = NwSheet.Cells[1, iCnt].Value2;
                                StaticVariable.dtReadData.Add(temp.Trim(), Convert.ToString(NwSheet.Cells[rCnt1, iCnt].Value2));
                            }


                            //if (Convert.ToString(NwSheet.Cells[rCnt1, cCnt1 - 2].Value2) == "fn_AddNum" || Convert.ToString(NwSheet.Cells[rCnt1, cCnt1 - 2].Value2) == "fn_SubNum")
                            //{
                            //    //StaticVariable.intParam1 = Convert.ToInt32(NwSheet.Cells[rCnt1, cCnt1 + 4].Value2);
                            //    //StaticVariable.intParam2 = Convert.ToInt32(NwSheet.Cells[rCnt1, cCnt1 + 5].Value2);
                            //    object[] mParam1 = new object[] { Convert.ToInt32(StaticVariable.dtReadData["InParam1"]), Convert.ToInt32(StaticVariable.dtReadData["InParam2"]) };
                            //    object result = mthInfo.Invoke(this, mParam1);
                            //    StaticVariable.intOutParam1 = Convert.ToInt32(result);
                            //    NwSheet.Cells[rCnt1, cCnt1 + 2].Value2 = Convert.ToString(StaticVariable.intOutParam1) != "" ? Convert.ToString(StaticVariable.intOutParam1) : String.Empty;
                            //}

                            //else
                            //{
                                object[] mParam = new object[] { };
                                mthInfo.Invoke(magicClassObject, mParam);