Crear una instancia de un objeto con un tipo determinado por el tiempo de ejecución

Estoy en una situación en la que me gustaría crear una instancia de un objeto de un tipo que se determinará en tiempo de ejecución. También necesito realizar un lanzamiento explícito a ese tipo.

Algo como esto:

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); } 

Obviamente, este no es un código válido, pero espero que transmita la esencia de lo que estoy tratando de hacer. El método en el que estoy trabajando tendrá que realizar la operación de cálculo de referencias en ~ 35 tipos diferentes. Tengo varios otros métodos que deberán hacer algo similar con el mismo conjunto de tipos. Por lo tanto, me gustaría aislar la lógica de determinación del tipo de estos métodos para que solo tenga que escribirla una vez, y para que los métodos se mantengan limpios y legibles.

Debo admitir que soy un novato total en el diseño. ¿Alguien podría sugerir un buen enfoque para este problema? Sospecho que podría haber un patrón de diseño apropiado que desconozco.

Hay varias formas de crear un objeto de cierto tipo sobre la marcha, una es:

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

Y obtendrás una instancia de MyClass en obj.

Otra forma es usar la reflexión:

 // 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[] { }); 

Y a partir de uno de ConstructorInfo devuelto, puede “Invocarlo ()” con argumentos y obtener una instancia de la clase como si hubiera usado un operador “nuevo”.

En general, puede hacer lo que está describiendo, pero como no conoce el tipo en tiempo de comstackción, deberá mantener la instancia sin tipear; compruebe su tipo en cada punto que usa y, a continuación, empújelo correctamente (esto no será necesario con c # 4.0, que admite la dinámica ):

 Type type = CustomGetTypeMethod(); var obj = Activator.CreateInstance(type); ... if(obj is MyCustomType) { ((MyCustomType)obj).Property1; } else if (obj is MyOtherCustomType) { ((MyOtherCustomType)obj).Property2; } 

Creo que estás buscando Activator.CreateInstance

Crear una instancia de un Type determinado en tiempo de ejecución es fácil, usando Activator.CreateInstance , como han mencionado otros. Sin embargo, Marshal.PtrToStructure , como lo hace en su ejemplo en la línea Marshal.PtrToStructure , no es posible, ya que el tipo debe conocerse en tiempo de comstackción para la conversión. Además, tenga en cuenta que Activator.CreateInstance no se puede usar junto con un IntPtr.

Si sus tipos tienen una clase base común (que no sea Object ), puede convertirlo a dicho tipo de base y llamar funciones sobre eso. De lo contrario, las funciones de llamada solo serán posibles mediante la reflexión.

Entonces o bien:

 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(); } 

O:

 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..); } 

Podrías ir 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; } } } } 
  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);