【问题标题】:.NET generic class instance - passing a variable data type.NET 泛型类实例 - 传递可变数据类型
【发布时间】:2010-06-02 00:52:05
【问题描述】:

正如标题所示,我很想将变量数据类型传递给模板类。像这样的:

frmExample = New LookupForm(Of Models.MyClass) 'Works fine

Dim SelectedType As Type = InstanceOfMyClass.GetType() 'Works fine
frmExample = New LookupForm(Of SelectedType) 'Ba-bow!
frmExample = New LookupForm(Of InstanceOfMyClass.GetType()) 'Ba-bow!

LookupForm<Models.MyClass> frmExample;
Type SelectedType = InstanceOfMyClass.GetType();
frmExample = new LookupForm<SelectedType.GetType()>(); //Ba-bow
frmExample = new LookupForm<(Type)SelectedType>(); //Ba-bow

我假设这与编译时正在处理的模板有关,但即使我在那里不合时宜,它也无法解决我的问题。我也找不到任何有关使用反射来实例化模板类的相关信息。

(如何)在运行时创建动态类型存储库的实例?

【问题讨论】:

标签: c# vb.net generics reflection dynamic-typing


【解决方案1】:

一个非常接近的 C# 示例位于 here 我有一个问题:

typeof(MyClass).GetMethod("Foo").MakeGenericMethod(new[] { param.GetType() }).Invoke(null, new[] { param });

转换为 VB.NET,将其更改为类型创建而不是方法调用,并为您使用示例名称:

Dim frmExample as LookupForm<Models.MyClass>;
Dim SelectedType as Type = InstanceOfMyClass.GetType();   
Dim GenericLookupType as Type = GetType(LookupForm(Of)).MakeGenericType(SelectedType)
frmExample = Activator.CreateInstance(GenericLookupType, new object(){})

(啊,出于某种原因,我以为你想要在 VB.NET 中使用它,但这是一个 C# 示例)

LookupForm<Models.MyClass> frmExample;
Type SelectedType = InstanceOfMyClass.GetType();   
Type GenericLookupType = typeof(LookupForm<>).MakeGenericType(SelectedType);
frmExample = Activator.CreateInstance(GenericLookupType, new object[]{});

【讨论】:

  • 可能是因为原标题开头有 VB.NET,而问题只有一个 VB.NET 示例 :) 我删除了标题引用并添加了一个 C#,希望能够挖掘更大的思维方式。跨度>
  • 感谢您的接受。你会发现很多关于这类东西的大多数应用的小兔子洞,但这是找到语言边界情况的好方法。
【解决方案2】:

使用Type.MakeGenericType

Type modelType = typeof(Models.MyClass);
var repoType = typeof(LookupForm<>).MakeGenericType(new [] {modelType} );
//at this point repoType == typeof(LookupForm<Models.MyClass>);
var repo = Activator.CreateInstance(repoType );
//Ta-dah!!!

还有 VB.NET 版本:)

    Dim modelType As Type = GetType(Models.MyClass)
    Dim repoType As Type = GetType(LookupForm(Of )).MakeGenericType(New Type() {modelType})
    'at this point repoType = GetType(LookupForm(of Models.MyClass))'
    Dim repo = Activator.CreateInstance(repoType)
    'Ta-dah!!!'

【讨论】:

    【解决方案3】:

    这听起来像是动态语言运行时的候选者,C# 中的“动态”类型,但这需要您使用 .NET 4.0

    【讨论】:

    • 我认为您仍然必须使用 Activator.CreateInstance 但您可以在编译时更好地处理它{即LookupForm a = (LookupForm)Activator.CreateInstance(etc.);并确保 SomeInstanceType 匹配其他动态生成的类型。现在有点难以解释,但你无疑知道我的意思。
    【解决方案4】:

    不幸的是,如果不进行反思,您将无法做到这一点,即使如此,它也不是很友好。反射代码将如下所示:

    Type baseType = typeof(LookupForm<>);
    Type selectedType = InstanceOfMyClass.GetType(); //or however else you want to get hold of it
    Type genericType = baseType.MakeGenericType(new Type[] { selectedType });
    object o = Activator.CreateInstance(genericType);
    

    当然,现在您不知道要将对象转换为什么(假设 selectedType 是动态设置的),但您仍然可以通过反射调用其上的方法,或者您可以创建一个非泛型接口进行转换它来调用它的方法。

    【讨论】:

    • 它在实现上不一定要友好,只要界面很好:)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-12-23
    • 1970-01-01
    • 2010-09-20
    • 1970-01-01
    相关资源
    最近更新 更多