使用运行时确定的类型实例化对象

Odr*_*ade 60 .net c# design-patterns runtime

我处于这样一种情况,我想要实例化一个将在运行时确定的类型的对象.我还需要对该类型执行显式转换.

像这样的东西:

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);
}
Run Code Online (Sandbox Code Playgroud)

这显然不是有效的代码,但我希望它传达了我想要做的事情的本质.我实际工作的方法必须在~35种不同的类型上执行编组操作.我有几个其他方法需要使用相同的类型集来做类似的事情.所以,我想从这些方法中分离出类型决定逻辑,这样我只需要编写一次,这样方法就可以保持清晰和可读.

我必须承认自己是设计界的新手.有谁能建议一个很好的方法解决这个问题?我怀疑可能有一个我不知道的合适的设计模式.

cha*_*rit 117

有几种方法可以动态创建某种类型的对象,一种是:

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

// create an object of the type
var obj = (MyClass)Activator.CreateInstance(type);
Run Code Online (Sandbox Code Playgroud)

你将在obj中获得MyClass的一个实例.

另一种方法是使用反射:

// 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[] { });
Run Code Online (Sandbox Code Playgroud)

并且从返回的ConstructorInfo之一,您可以使用参数"调用()"它并获取类的实例,就像您使用了"new"运算符一样.

  • 这并没有(完全)回答这个问题.他在编译时不知道它是`MyClass`还是`HisClass`还是`HerClass`(运行时确定的类型). (21认同)
  • @ mini-me请注意,在OP的问题中包括`Type structType = getTypeFromEnum(val);`.我只是添加一个示例代码来演示首先应该获得`Type`实例. (4认同)
  • @ mini-me这只是一个例子.OP正在寻找一个API来做到这一点.代码就足以回答了.我不能让所有的东西按照OP想要的方式进行编译,这对OP来说真的没有帮助.和IMO实际上大多数情况下,你至少会知道并希望对象基于某些基类型或接口,并且几乎总是永远不会完全动态或只是简单的`Object`,因为它们是非常无用的(或者不需要运行时反思使用.) (2认同)
  • 而不是`typeof(MyClass)`我使用`inputObj.GetType()`.这提供了类型,但可能不适用于投射.就我而言,我有一个合适的父母足以进行投射. (2认同)

Rex*_*x M 15

几乎可以完成你所描述的内容,但由于你在编译时不知道类型,你必须保持实例的松散类型; 在你使用它的每个点检查它的类型,并适当地投射它(这对于支持动态的 c#4.0不是必需的):

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

...


if(obj is MyCustomType)
{
    ((MyCustomType)obj).Property1;
}
else if (obj is MyOtherCustomType)
{
    ((MyOtherCustomType)obj).Property2;
}
Run Code Online (Sandbox Code Playgroud)


Jas*_*yon 10

我想你正在寻找Activator.CreateInstance

  • 是的,我也是。我用这个来帮助。http://stackoverflow.com/questions/752/get-a-new-object-instance-from-a-type-in​​-c (2认同)

Ais*_*ina 6

正如其他人所提到的那样Type,创建一个运行时确定的实例很容易Activator.CreateInstance.但是,正如您在示例中所做的那样,Marshal.PtrToStructure无法进行转换,因为必须在编译时知道类型以进行转换.另请注意,Activator.CreateInstance不能与IntPtr一起使用.

如果您的类型具有公共基类(除了Object),则可以将其转换为所述基类型并在其上调用函数.否则,只能使用反射调用函数.

所以要么:

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();
}
Run Code Online (Sandbox Code Playgroud)

要么:

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..);
}
Run Code Online (Sandbox Code Playgroud)