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

发布于 2024-07-23 12:07:18 字数 664 浏览 4 评论 0原文

我现在的情况是,我想实例化一个在运行时确定类型的对象。 我还需要执行对该类型的显式转换。

像这样的事情:

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

这显然不是有效的代码,但我希望它传达了我想要做的事情的本质。 我实际正在研究的方法必须对大约 35 种不同类型执行封送操作。 我还有其他几种方法需要对同一组类型执行类似的操作。 因此,我想将类型确定逻辑与这些方法隔离开来,这样我只需要编写一次,从而使这些方法保持干净和可读。

我必须承认我在设计方面完全是个新手。 有人能提出解决这个问题的好方法吗? 我怀疑可能存在我不知道的合适的设计模式。

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

淤浪 2024-07-30 12:07:18

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

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

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

并且您将在 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[] { });

从返回的 ConstructorInfo 之一中,您可以使用参数“Invoke()”它并返回该类的实例,就像使用“new”运算符一样。

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.

深府石板幽径 2024-07-30 12:07:18

您可以大部分执行您所描述的操作,但由于您在编译时不知道类型,因此必须保持实例松散类型; 在使用它的每个点检查它的类型,然后适当地转换它(这对于 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;
}

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;
}
傲世九天 2024-07-30 12:07:18

我认为您正在寻找 Activator.CreateInstance

I think you're looking for Activator.CreateInstance

错爱 2024-07-30 12:07:18

正如其他人提到的,使用 Activator.CreateInstance 创建运行时确定的 Type 实例很容易。 但是,无法像在 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();
}

或者:

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

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..);
}
甜中书 2024-07-30 12:07:18

你可以变得动态:

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

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; }
        }
    }
}
维持三分热 2024-07-30 12:07:18
 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);
 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);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文