【问题标题】:Generate Generic Type At Runtime在运行时生成泛型类型
【发布时间】:2011-06-30 21:42:07
【问题描述】:

我想知道是否可以将一个变量的类型设置为另一个泛型变量的类型?

例如,假设我有这个代码:

public class Foo: IBar<ushort>
{
    public FooBar()
    {
        Value = 0;
    }

    public ushort Value { get; private set; }
}

我也有这门课:

public class FooDTO<TType> : IBar<TType>
{
    public TType Value { get; private set; }
}

在这些示例中,在 IBar 的接口中具有属性

TType Value;

然后在我的代码中我有这个

var myFoo = new Foo();
var fooDataType = myFoo.Value.GetType();

//I know this line of code does not compile, but this is what I am looking to be able to do
var myFooDTO= new FooDTO<fooDataType>();

我正在寻找的可能吗?对于高使用率的代码会不会太慢(因为使用了反射。

【问题讨论】:

  • 为什么?你想做什么?

标签: c# generics reflection types runtime


【解决方案1】:

您可以通过反射,使用Type.MakeGenericType 来做到这一点。

由于反射,这会产生一些开销,因此您需要对其进行分析以查看这是否会成为您的问题。

【讨论】:

    【解决方案2】:

    您正在寻找编译时反射,这是 C# 所没有的功能。因此,如果您正在寻找性能优化,解决方案比问题更糟糕。

    D 确实有这个功能;你可以轻松写

    int x = 0;
    typeof(x) y = x + 2;
    

    甚至是 D 中更复杂的表达式,并且都在编译时进行评估。

    【讨论】:

      【解决方案3】:

      当我在一个句子中阅读“通用”和“运行时”时,我总是认为“糟糕的设计”或“不理解通用的含义”。可能两者兼而有之。

      泛型参数是类型的组成部分。所以说“在运行时生成通用类型”与“在运行时生成 Foo 类”相同。您正在寻找算法的反射或更改设计。

      在这种情况下,var 关键字也无济于事。算了。

      【讨论】:

        【解决方案4】:

        为什么不使用方法类型推断:

        public class FooDTO<TType> {
            public TType Value { get; private set; }
        }
        
        public class Foo : FooDTO<ushort> { }
        
        static FooDTO<T> GetTypedFoo<T>(T Obj) {
            return new FooDTO<T>();
        }
        
        static void Main(string[] args) {
           Foo F = new Foo();
        
           var fooDTO = GetTypedFoo(F.Value);
        }
        

        【讨论】:

        • 应该是@Object,或者更好的obj。我在写同样的东西,所以我会给你一个 +1。
        【解决方案5】:

        你想要的核心是:

        var type = typeof(FooDTO<>).MakeGenericType(fooDataType);
        object obj = Activator.CreateInstance(type);
        

        但是,您会注意到这是反射,并且几乎将您与object 联系在一起。通常的解决方法是访问 API 的非通用版本,以便您可以使用 object - 例如(添加非通用 IBar):

        IBar bar = (IBar)Activator.CreateInstance(type);
        

        您当然可以将运行时/泛型命中更高 - 也许进入泛型方法;那么泛型方法中的所有内容都可以使用T,并且您可以使用MakeGenericMethod 在仅在运行时知道的特定T 的上下文中执行该方法。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-08-19
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多