【问题标题】:C# Generic method and dynamic type problem [duplicate]C#泛型方法和动态类型问题[重复]
【发布时间】:2011-08-23 03:21:09
【问题描述】:

我有一个通用方法声明如下:

public void Duplicate<EntityType>() { ... }

所以,通常要使用它,我只需要说:

myObject.Duplicate<int>()

但是在这里,我想做的是通过变量传递类型,但这不起作用,这是我尝试这样做的方法:

Type myType = anObject.GetType();
myObject.Duplicate<myType>();

如果有人可以帮助我?

提前致谢。

【问题讨论】:

    标签: c# generics parameters types


    【解决方案1】:

    基本上你必须使用反射:

    MethodInfo method = typeof(...).GetMethod("Duplicate");
    MethodInfo generic = method.MakeGenericMethod(myType);
    generic.Invoke(myObject, null);
    

    【讨论】:

    • 有一天我会按照您的建议发布然后修改。再次被殴打以再次检查方法名称。 :) +1
    • 应该做的伎俩,我会测试它。谢谢
    • 嘿,@Jon,我知道你的答案可以追溯到大约 5 年前,也许 MethodInfo.Invoke 方法曾经有一个重载(如果不是唯一的),它需要一个参数,但现在就是这样不是这样。如果要调用的方法不带任何参数,我们至少需要传递null。在另一种情况下,Duplicate 方法可能会出现重载,这将引发 AmbiguousMatchException。我相信你知道,但我还是想加两分钱。
    • @MikayilAbdullayev:添加了null 参数。
    【解决方案2】:

    如果您将类型作为变量,那么您实际上并没有很好的泛型方法候选者,尤其是当您的方法没有返回任何内容时。

    你会更好:

    public void Duplicate(Type entityType) { ... }
    

    那么你的代码就变成了:

    Type myType = anObject.GetType();
    myObject.Duplicate(myType);
    

    您可以使用 Jon Skeet 的(正确)答案通过反射调用您的方法,但我看不出这种方法是通用的。

    泛型的目的是保留类型 - 这样您就不必对值类型进行装箱/拆箱等操作。

    但是,您的重复方法没有返回(它是void)并且没有输入参数。本质上,唯一的输入是类型参数。这意味着在您的通用方法中的某个地方,您可能正在执行以下操作:

    public void Duplicate<EntityType>() 
    {
     ...
     Type inputType = typeof(EntityType); 
     ...
    }
    

    在这种情况下,EntityType 是一个通用类型参数而不是常规输入参数,你并没有获得任何好处,而且当你不知道输入时,你增加了对笨拙和缓慢反射的需求编译时间。

    【讨论】:

      【解决方案3】:

      您可以使用将 Type 作为参数的标准方法:

      myobject.Duplicate(myType);
      

      或者您可以尝试使用反射,例如:

      System.Reflection.MethodInfo mi = typeof(TypeOfMyObject).GetMethod("Duplicate<>");
      MethodInfo constructedMethodInfo = mi.MakeGenericMethod(new type[] {myType});
      constructedMethodInfo.Invoke(myObject, new object[] {});
      

      【讨论】:

        【解决方案4】:

        Duplicate() 的具体功能还不是很清楚,但是当您要传递给 Duplicate() 的类型是类或 int 时,下面的示例可以工作。

        本质上,不要传入类型,传入示例对象。此测试方法说明调用(一种方法中的两个测试)

            [TestMethod]
            public void TestMethod1()
            {
                var myObject = new AnObject { AString = "someString" };
        
                var myOtherObject = new AnotherObject();
                var newObject = myObject.Duplicate(myOtherObject);
                Assert.IsTrue(newObject.AString=="someString");
        
                var newObject2 = myObject.Duplicate(1);
                Assert.IsTrue(newObject2 is Int32);
            }
        

        Duplicate() 方法有一个链接到示例对象的类型参数,但不需要使用作为参数给出的类型来调用,它从示例对象中推断出来。

        这是具有 Duplicate() 方法的类:

        public class AnObject
        {
            public string AString { get; set; }
        
            public T Duplicate<T>(T exampleObject)
                where T: new()
            {
                var newInstance = (T)Activator.CreateInstance<T>();
        
                // do some stuff here to newInstance based on this AnObject
                if (typeof (T) == typeof (AnotherObject))
                {
                    var another = newInstance as AnotherObject;
                    if(another!=null)
                        another.AString = this.AString;
                }
        
                return newInstance;
            }
        }
        

        为了完成图片,这是AnotherObject类。

        public class AnotherObject
        {
            public string AString { get; set; }
        }
        

        当传入的类型是 int 之类的值类型时,此代码在 Duplicate() 方法内部可能会出现一些问题。这取决于您希望 Duplicate() 对 int 做什么(您可能必须将其作为可为空的 int 传递)。

        它适用于引用类型(类)。

        【讨论】:

        • 实际上,如果你走的是通用路线,我认为基思的回复比我的更好。不需要示例类型。我假设它有效,并且您不需要返回值。
        • 我假设 Duplicate() 旨在返回传入类型的克隆,但您的问题表明没有返回值。
        猜你喜欢
        • 1970-01-01
        • 2019-06-04
        • 1970-01-01
        • 2014-07-06
        • 2017-01-15
        • 1970-01-01
        • 2021-04-10
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多