如何将没有接口的泛型类型传递给Of T函数

时间:2021-08-09 15:01:16

I have a following code which works fine

我有以下代码,工作正常

MsgBox(AddSomething(Of String)("Hello", "World"))

Public Function AddSomething(Of T)(ByVal FirstValue As T, ByVal SecondValue As T) As String
    Return FirstValue.ToString + SecondValue.ToString
End Function

Now we are redesigning the application to work with parameters of different types which will be provided through XML

现在我们正在重新设计应用程序以使用将通过XML提供的不同类型的参数

  <SomeValues>
    <Add Param1="Somedata" Param2="SomeData" MyType="String"/>
    <Add Param1="Somedata" Param2="SomeData" MyType="MyBusinessObject"/>
  </SomeValues>

If I try to provide the following it gives error as Of accepts only type

如果我尝试提供以下内容,则会显示错误,因为仅接受类型

    ''''Get DetailsFromXml --- MyType,Param1,Param2
    MsgBox(AddSomething(Of Type.GetType(MyType))(Param1,Param2))

How to solve this issue.

如何解决这个问题。

Edit

The above example is given to make the question simple. Actual issue is as follows I am using SCSF of P&P. Following is per view code which has to be written for each view

上面的例子是为了简化问题。实际问题如下我正在使用P&P的SCSF。以下是必须为每个视图编写的每个视图代码

Private Sub tsStudentTableMenuClick()
    Dim _StudentTableListView As StudentListView
    _StudentTableListView = ShowViewInWorkspace(Of StudentListView)("StudentTable List", WorkspaceNames.RightWorkspace)
    _StudentTableListView.Show()
End Sub

Now I want to show the views dynamically.

现在我想动态显示视图。

 Public Sub ShowModalView(ByVal ViewName As String)
        Dim _MasterListView As >>>EmployeeListView<<<<
        _MasterListView = ShowViewInWorkspace(Of >>>EmployeeListView<<<)("Employee List", WorkspaceNames.RightWorkspace)
        _MasterListView.Show()
    End Sub

So the part shown using the arrows above has to be somehow dynamically provided.

所以使用上面箭头显示的部分必须以某种方式动态提供。

3 个解决方案

#1


The point of generics is to provide extra information at compile-time. You've only got that information at execution-time.

泛型的关键是在编译时提供额外的信息。您只在执行时获得了该信息。

As you're using VB, you may be able to get away with turning Option Strict off to achieve late binding. I don't know whether you can turn it off for just a small piece of code - that would be the ideal, really.

当您使用VB时,您可以通过关闭Option Strict来实现延迟绑定。我不知道你是否可以只为一小段代码关闭它 - 这将是理想的,真的。

Otherwise, and if you really can't get the information at compile-time, you'll need to call it with reflection - fetch the generic "blueprint" of the method, call MethodInfo.MakeGenericMethod and then invoke it.

否则,如果你真的无法在编译时获取信息,你需要用反射调用它 - 获取方法的通用“蓝图”,调用MethodInfo.MakeGenericMethod然后调用它。

I assume that the real method is somewhat more complicated? After all, you can call ToString() on anything...

我认为真正的方法有点复杂吗?毕竟,你可以在任何东西上调用ToString()......

(It's possible that with .NET 4.0 you'll have more options. You could certainly use dynamic in C# 4.0, and I believe that VB10 will provide the same sort of functionality.)

(有可能在.NET 4.0中你会有更多的选择。你当然可以在C#4.0中使用动态,我相信VB10将提供相同的功能。)

#2


In .Net generics, you must be able to resolve to a specific type at compile time, so that it can generate appropriate code. Any time you're using reflection, you're resolving the type at run time.

在.Net泛型中,您必须能够在编译时解析为特定类型,以便它可以生成适当的代码。只要您使用反射,就可以在运行时解析类型。

In this case, you're always just calling the .ToString() method. If that's really all your code does, you could just change the parameter type to Object rather than use a generic method. If it's a little more complicated, you could also try requiring your parameters to implement some common interface that you will define.

在这种情况下,您总是只调用.ToString()方法。如果这确实是你的所有代码所做的,你可以将参数类型更改为Object而不是使用泛型方法。如果它有点复杂,您还可以尝试使用您的参数来实现您将定义的一些通用接口。

#3


If all you are doing is ToString, then making the parameters object instead would solve the problem in the simplest way. Otherwise you are going to have to bind the type at run-time, which in C# looks like:

如果你所做的只是ToString,那么制作参数对象将以最简单的方式解决问题。否则你将不得不在运行时绑定类型,在C#中看起来像:

System.Reflection.MethodInfo mi = GetType().GetMethod("AddSomething");
mi = mi.MakeGenericMethod(Type.GetType(MyType));
object result = mi.Invoke(this, new object[] { Param1, Param2 });

Because it involves reflection it won't be fast though... but I assume that's not a problem in this context.

因为它涉及反射它虽然不会很快......但我认为在这种情况下这不是问题。

#1


The point of generics is to provide extra information at compile-time. You've only got that information at execution-time.

泛型的关键是在编译时提供额外的信息。您只在执行时获得了该信息。

As you're using VB, you may be able to get away with turning Option Strict off to achieve late binding. I don't know whether you can turn it off for just a small piece of code - that would be the ideal, really.

当您使用VB时,您可以通过关闭Option Strict来实现延迟绑定。我不知道你是否可以只为一小段代码关闭它 - 这将是理想的,真的。

Otherwise, and if you really can't get the information at compile-time, you'll need to call it with reflection - fetch the generic "blueprint" of the method, call MethodInfo.MakeGenericMethod and then invoke it.

否则,如果你真的无法在编译时获取信息,你需要用反射调用它 - 获取方法的通用“蓝图”,调用MethodInfo.MakeGenericMethod然后调用它。

I assume that the real method is somewhat more complicated? After all, you can call ToString() on anything...

我认为真正的方法有点复杂吗?毕竟,你可以在任何东西上调用ToString()......

(It's possible that with .NET 4.0 you'll have more options. You could certainly use dynamic in C# 4.0, and I believe that VB10 will provide the same sort of functionality.)

(有可能在.NET 4.0中你会有更多的选择。你当然可以在C#4.0中使用动态,我相信VB10将提供相同的功能。)

#2


In .Net generics, you must be able to resolve to a specific type at compile time, so that it can generate appropriate code. Any time you're using reflection, you're resolving the type at run time.

在.Net泛型中,您必须能够在编译时解析为特定类型,以便它可以生成适当的代码。只要您使用反射,就可以在运行时解析类型。

In this case, you're always just calling the .ToString() method. If that's really all your code does, you could just change the parameter type to Object rather than use a generic method. If it's a little more complicated, you could also try requiring your parameters to implement some common interface that you will define.

在这种情况下,您总是只调用.ToString()方法。如果这确实是你的所有代码所做的,你可以将参数类型更改为Object而不是使用泛型方法。如果它有点复杂,您还可以尝试使用您的参数来实现您将定义的一些通用接口。

#3


If all you are doing is ToString, then making the parameters object instead would solve the problem in the simplest way. Otherwise you are going to have to bind the type at run-time, which in C# looks like:

如果你所做的只是ToString,那么制作参数对象将以最简单的方式解决问题。否则你将不得不在运行时绑定类型,在C#中看起来像:

System.Reflection.MethodInfo mi = GetType().GetMethod("AddSomething");
mi = mi.MakeGenericMethod(Type.GetType(MyType));
object result = mi.Invoke(this, new object[] { Param1, Param2 });

Because it involves reflection it won't be fast though... but I assume that's not a problem in this context.

因为它涉及反射它虽然不会很快......但我认为在这种情况下这不是问题。