Ern*_*ieL 3 .net c# generics reflection
目标是基于调用my方法的类型创建一个通用实例.
问题是,当从泛型调用时,StackFrame似乎只包含开放定义类型参数而不是封闭定义类型参数.如何从StackFrame中获取类型参数?与此问题类似.我想我的情况有所不同,因为Log.Debug是从一个封闭的方法调用的.
如果StackFrame不是正确的方法,除IoC以外的任何建议?此代码用于填写对我的Unity容器的引用不可用的情况.
using System;
using System.Reflection;
namespace ReflectionTest
{
public class Logger
{
private readonly string loggerName;
protected Logger(string loggerName) { this.loggerName = loggerName; }
public void Debug(string message) { Console.WriteLine(string.Format("{0} - {1}", loggerName, message)); }
}
public class Logger<T> : Logger
{
public Logger() : base(typeof(T).FullName) { }
}
public static class Log
{
public static void Debug(string message)
{
// Determine the calling function, and create a Logger<T> for it.
System.Diagnostics.StackFrame frame = new System.Diagnostics.StackFrame(1);
MethodBase method = frame.GetMethod();
/// When method is from a generic class,
/// the method.ReflectedType definintion is open: Type.ContainsGenericParameters is true
/// How do I get the generic parameters of method.ReflectedType so
/// Activator.CreateInstance() will not throw?
Type logType = typeof(Logger<>);
Type constructed = logType.MakeGenericType(new Type[] { method.ReflectedType });
Logger logger = (Logger)Activator.CreateInstance(constructed);
logger.Debug(message);
}
}
public class MyBase<T>
{
public void Run()
{
Log.Debug("Run Generic"); // throws on Activator.CreateInstance()
}
}
class Program
{
static void Works()
{
Log.Debug("Run NonGeneric"); // works
}
static void DoesNotWork()
{
MyBase<int> b = new MyBase<int>();
b.Run();
}
static void Main(string[] args)
{
Works();
DoesNotWork();
}
}
}
Run Code Online (Sandbox Code Playgroud)
Eri*_*ert 17
堆栈帧不可靠,仅用于调试目的.你不能假设有任何有用的东西.这就是它在"诊断"命名空间中的原因.
但更一般地说,您的问题表明了对堆栈框架告诉您的内容存在根本性的误解.你说
目标是基于调用my方法的类型创建一个通用实例.
堆栈框架实际上并没有告诉您谁调用了您的方法.堆栈框架告诉您控件将返回的位置.堆栈框架是延续的具体化.这个事实谁调用的方法,并在那里控制将返回到几乎总是同样的事情,是你的问题的根源,但我向你保证,他们需要是不一样的.
特别是,目前预览版中即将出现的"异步/等待"功能证明了这一点.从await恢复的代码在堆栈框架上没有关于谁最初调用它的线索; 这些信息永远消失了.由于下一个要运行的代码在逻辑上与最初调用该方法的代码分离,因此堆栈帧不包含该信息.
我们不需要像这样充满异国情调.例如,假设方法M包含对方法N的调用,并且N调用方法O.如果抖动选择在M中内联N,则从O观察到的堆栈帧将不包含N.堆栈帧告诉您控制在何处当前方法返回时恢复.当O返回时,控制将在M内恢复,而不是N,因此堆栈帧不包含关于N的任何信息.
| 归档时间: |
|
| 查看次数: |
975 次 |
| 最近记录: |