使用 System.Type 中的泛型类型调用泛型方法
下面是代码示例和问题,请注意我不能使用 C# 4.0 和动态关键字。
static class TestClass
{
static void Main(string[] args)
{
Object o = "Previous value";
Test(ref o);
Trace.WriteLine(o);
}
static public void Test<T>(ref T obj)
{
// The goal is to somehow invoke Test2 with the real type of obj, i.e the type in obj.GetType()
// 1st try:
Test2(ref obj); // This doesn't work because the type in Test2 will be the same as T here.
// 2nd try:
MethodInfo mi = typeof(TestClass).GetMethod("Test2");
mi = mi.MakeGenericMethod(new Type[] { obj.GetType() });
mi.Invoke(null, new Object[] { obj }); // obj is no longer by reference so we need to store the object array and copy back the result after the call
// 3rd try, successful implementation by the smartest mind of stack overflow :)
}
static public void Test2<T>(ref T s)
{
if (typeof(T) == typeof(String))
{
s = (T)(Object)"Hello world!";
}
}
}
我还使用 Delegate.CreateDelegate 尝试了更多方法,但没有任何运气。 这有可能吗?
编辑:我并不害怕使用动态方法(和 MSIL 汇编器),但我在这方面的知识非常有限。
Edit2:这是一个更接近我真正想做的事情的例子:
public static class TypeHandler<T>
{
public delegate void ProcessDelegate(ref T value);
public static readonly ProcessDelegate Process = Init();
private static ProcessDelegate Init()
{
// Do lot's of magic stuff and returns a suitable delegate depending on the type
return null;
}
}
static class TestClass
{
static public void Main(string[] args)
{
Object o = "Previous value";
Test(ref o);
Trace.WriteLine(o);
}
static public void Test<T>(ref T obj)
{
if (obj is T)
{
// Optimized, common case
TypeHandler<T>.Process(ref obj);
return;
}
Type t = obj.GetType();
// How to call the delegate found in TypeHandler<t>.Process ? (I can get delegate but I can't call it).
}
}
below is a code example and the question, please note that I can NOT use C# 4.0 and the dynamic keyword.
static class TestClass
{
static void Main(string[] args)
{
Object o = "Previous value";
Test(ref o);
Trace.WriteLine(o);
}
static public void Test<T>(ref T obj)
{
// The goal is to somehow invoke Test2 with the real type of obj, i.e the type in obj.GetType()
// 1st try:
Test2(ref obj); // This doesn't work because the type in Test2 will be the same as T here.
// 2nd try:
MethodInfo mi = typeof(TestClass).GetMethod("Test2");
mi = mi.MakeGenericMethod(new Type[] { obj.GetType() });
mi.Invoke(null, new Object[] { obj }); // obj is no longer by reference so we need to store the object array and copy back the result after the call
// 3rd try, successful implementation by the smartest mind of stack overflow :)
}
static public void Test2<T>(ref T s)
{
if (typeof(T) == typeof(String))
{
s = (T)(Object)"Hello world!";
}
}
}
I also tried some more methods using Delegate.CreateDelegate but without any luck.
Is this at all possible?
Edit: I'm not afraid of using a dynamic method (and MSIL assembler) but my knowledge in this area is very limited.
Edit2: Here's an example that is closer to what I really trying to do:
public static class TypeHandler<T>
{
public delegate void ProcessDelegate(ref T value);
public static readonly ProcessDelegate Process = Init();
private static ProcessDelegate Init()
{
// Do lot's of magic stuff and returns a suitable delegate depending on the type
return null;
}
}
static class TestClass
{
static public void Main(string[] args)
{
Object o = "Previous value";
Test(ref o);
Trace.WriteLine(o);
}
static public void Test<T>(ref T obj)
{
if (obj is T)
{
// Optimized, common case
TypeHandler<T>.Process(ref obj);
return;
}
Type t = obj.GetType();
// How to call the delegate found in TypeHandler<t>.Process ? (I can get delegate but I can't call it).
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
您的评论看起来您已经了解如何做到这一点:
这实际上只是将您的评论变成代码。这是否不符合您的要求?
Your comment looks like you already understand how to do it:
That's really just turning your comment into code. Does that somehow not do what you want?
我认为主要问题是,你想做什么?
如果您只想将字符串分配给引用对象,您可以尝试以下操作:
泛型可以在运行时定义,但它不是很舒服,必须通过反射来完成......在我看来,这是“不行”,但只是一个意见
尝试使用
object.GetType()
来获取对象的当前类型。The main questions, in my opinion is, what do you want to do?
If you just want to assign a string to a reference object you could try this:
Generics can be defined during runtime, but it's not verry comfortable and has to be done by reflection ... in my oppinion it is a "no go", but just an oppinion
Try using the
object.GetType()
to get the current Type of the Object.更新 3:好的,既然您可以接受丑陋的解决方案,您可能需要查看未记录的解决方案
__refvalue
和__makeref
关键字。您的问题似乎是您希望能够指定要转换或更改的
ref object
参数的类型。这样做的问题是,例如,您不能随意将任何类型
T
的变量分配给string
。因此,您需要传入一个ref 对象
或ref string
才能正常工作。。在我看来, oberfreak 明确了你想要实现的目标(我最初没有注意到你已经初始化了
o
作为一个字符串
,因此显然希望其实际类型影响Test2
函数的行为)。他的回答对你来说是正确的方法。更新:您在评论中提到您想要做的是具有可以使用字典来实现的动态行为。我猜看起来是这样的?
更新 2:根据您的更新示例更新了此示例。
这应该可以。但你不能用泛型真正实现同样的目标,因为没有办法做到这一点(如你所知):
如果有,那么你就万事大吉了。但唯一可能的方法是使用反射,对于这样的事情来说,反射是丑陋且昂贵的,并且显然会违背您保持简单并确保良好性能的意图。
Update 3: OK, since you're fine with an ugly solution, you may want to check out the undocumented
__refvalue
and__makeref
keywords.It seems your issue is that you want to be able to specify the type for a
ref object
parameter to be converted or changed to.The problem with that is that you can't just arbitrarily assign a variable of any type
T
to astring
, for example. So you'd need to pass in aref object
orref string
for that to work at all.It looks to me like oberfreak nailed down what you were trying to achieve (I originally failed to notice you had initialized
o
as astring
and thus clearly wanted its actual type to influence the behavior of theTest2
function). His answer has the right approach for you.Update: you mention in a comment that what you're trying to do is have dynamic behavior which could be achieved using a dictionary. I'm guessing that looks something like this?
Update 2: updated this example based on your updated example.
That should work. But you can't really achieve the same thing with generics because there's no way to do this (as you know):
If there were, then you'd be all set. But the only possible way you can do that is by using reflection, which is ugly and expensive for something like this and would clearly defeat your intention of keeping this simple and ensuring good performance.
实现方法 Test2 的正确方法是
或者我在这里遗漏了一些东西?
The right way to implement method Test2 would be
Or am I missing something here?
如果您可以将
ref
更改为常规返回,则可以通过dynamic
在 4.0 中进行大规模作弊:现在是:
完整示例:
其中写入“Hello world!”
If you can change the
ref
to a regular return, you can cheat massively in 4.0 viadynamic
:that is now:
Full example:
which writes "Hello world!"