【问题标题】:How to use a variable as a Type?如何将变量用作类型?
【发布时间】:2023-04-09 21:37:01
【问题描述】:

我有一个作为 ISomething 传递给我的对象。 我需要序列化对象但是我的序列化器需要一个具体类型的类型参数,即:

string xml = Utilities.Serialize<ConcreteType>(myObject);

基本上我想和这个人一样:Creating a generic object based on a Type variable

但是我不想创建对象的新实例,我想使用生成的类型作为我的泛型类的参数。

所以,简而言之,我的问题是如何创建一些变量来表示可以与这样的泛型类一起使用的某个对象的具体类型:

string xml = Utilities.Serialize<ConcreteType>(myObject);

ConcreteType 是我需要创建的。

【问题讨论】:

  • 我不熟悉 .net 中的 Utilities.Serialize。您能否评论一下全名(所有命名空间)?
  • @CrazyCasta:没关系。 OP需要的是Utilities.SomeMethod&lt;someVariableContainingConcreteType&gt;(myObject)
  • 这无关紧要,我只是以它为例。为了澄清,我可能想制作一个 List ,其中 T 是我的问题的具体类型。
  • 所以他想调用一个由变量指定的泛型类型的方法?使用 ISerialize 似乎要容易得多。
  • 为什么Serialize() 是通用的?似乎没有一个很好的理由。如果确实需要该类型,那么将Type 作为普通参数的重载可能会更好。

标签: c#


【解决方案1】:

假设你有类似的东西:

public static class Util
{
    public static T Foo<T>(object obj)
    {
         // Do actual stuff here
         return default(T);
    }
}

通常,编译器会连接此方法的任何用法,根据您传递的内容交换适当的泛型变体。如果你有一个包含类型的变量,我们就不能再依赖编译器了——但是我们可以要求类给我们我们想要的变体:

public void DoFooWith(object blob)
{
    // Get the containing class
    var utilType = typeof(Util);
    // Get the method we want to invoke
    var baseMethod = utilType.GetMethod("Foo", new Type[]{typeof(object)});
    // Get a "type-specific" variant
    var typedForBlob = baseMethod.MakeGenericMethod(blob.GetType());
    // And invoke it
    var res = typedForBlob.Invoke(null, new[]{blob});
}

【讨论】:

    【解决方案2】:

    如果您绝对需要获取实际对象的类型,您可以使用 GetType()。问题是,您必须使用反射来调用所有函数,因为据我所知,没有简单的方法可以使用具有该类型的变量来调用它们。

    【讨论】:

      【解决方案3】:

      您不能保证所有 ISomething 都是 ConcreteType 的,但您可以投射它们并传递有效的。

      string CastAndSerialize(ISomething somthing)
      {
          //castSomthing will be null if ISomthing was not a ConcreteType.    
          ConcreteType castSomthing = somthing as ConcreteType; 
      
          if(castSomthing != null)
          {
             return Utilities.Serialize<ConcreteType>(castSomthing );
          }
          else
          {
              return null; //Or whatever you want to use to represent that the cast failed.
          }
      }
      

      这是一个更通用的版本,它适用于任何 class

      string CastAndSerialize<T>(ISomething somthing) where T : class
      { 
          T castSomthing = somthing as T; 
      
          if(castSomthing != null)
          {
             return Utilities.Serialize<T>(castSomthing );
          }
          else
          {
              return null;
          }
      }
      

      【讨论】:

      • 这两个示例都不能满足 OP 在运行时指定具体类型的需求。
      【解决方案4】:

      可能是另一种形式的泛型方法的情况。如果您拥有 Utilities.Serialize(...) 并且可以生成新的重载,请查看:

      http://msdn.microsoft.com/en-US/library/twcad0zb(v=VS.80).aspx

      例如:

      string Utilities.Serialize<T>(T object) 
          where T : ConcreteType
      

      经过进一步思考(双关语),您是否正在寻找以下内容?

      Calling a generic method with a dynamic type

      【讨论】:

      • 方法已经是泛型了,问题是在这种情况下如何调用它。
      • 哇,苛刻。我的思路是:Utilities.Serialize(myObject);做一些类似的事情: Utilities.Serialize(T object) where T : ConcreteType 这个问题虽然不是太具体,所以我的答案并没有太具体。我希望用户能提出更具体的问题。
      猜你喜欢
      • 2012-09-29
      • 1970-01-01
      • 2021-06-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-12-22
      • 1970-01-01
      相关资源
      最近更新 更多