在.NET中,使用反射如何获取方法中使用的类变量?
例如:
class A
{
UltraClass B = new(..);
SupaClass C = new(..);
void M1()
{
B.xyz(); // it can be a method call
int a = C.a; // a variable access
}
}
Run Code Online (Sandbox Code Playgroud)
注意:GetClassVariablesInMethod(M1 MethodInfo)返回B和C变量.通过变量,我指的是该特定变量的Value和/或Type和Constructor Parameters.
感谢 Jon Skeet 在这个问题中的回答,我进行了以下工作:
public delegate BaseItem GetItemDelegate(Guid itemID);
public static class Lists
{
public static GetItemDelegate GetItemDelegateForType(Type derivedType)
{
MethodInfo method = typeof(Lists).GetMethod("GetItem");
method = method.MakeGenericMethod(new Type[] { derivedType });
return (GetItemDelegate)Delegate.CreateDelegate(typeof(GetItemDelegate), method);
}
public static T GetItem<T>(Guid itemID) where T : class { // returns an item of type T ... }
}
public class DerivedItem : BaseItem { }
// I can call it like so:
GetItemDelegate getItem = Lists.GetItemDelegateForType(typeof(DerivedItem));
DerivedItem myItem = getItem(someID); // …Run Code Online (Sandbox Code Playgroud) 在WCF客户端应用程序中,有许多无参数方法,我们希望将结果缓存 - GetAllFoo(), GetAllBar(). 这些用于填充下拉列表等,结果在客户端的运行期间不会改变.
这些结果当前由存储在资源文件中的唯一字符串缓存 - 例如,GetAllCountries()缓存在CountryKey资源上.仅当缓存不包含请求的密钥时才会调用该服务.
public T Get<T, V>(string key, Func<V, T> serviceCall, V proxy)
{
if (!cache.Contains(key))
{
cache.Add(key, serviceCall(proxy));
}
return cache.GetData(key) as T;
}
Run Code Online (Sandbox Code Playgroud)
这很好,除了我们需要维护资源文件中的密钥,并且需要确保每个方法都使用正确的缓存密钥,否则会中断.旧的Control + C,Control + V在这里引起一些麻烦,我不想去检查每个调用此方法的地方.
所以问题是:
该serviceCall委托具有Method它属性描述要执行的方法.这是一个MethodInfo实例,它又包含一个MethodHandle属性.我是否正确地假设该MethodHandle属性唯一且一致地标识引用的方法?
我将包装器更改为
public T Get<T, V>(Func<V, T> serviceCall, V proxy)
{
var key = serviceCall.Method.MethodHandle;
// etc
Run Code Online (Sandbox Code Playgroud)
它正确地封装了缓存和关键问题,并消除了对调用者"做正确的事情"的任何依赖.
这是我之前提出的另一个问题的问题.我有一个重载的方法:
public void Add<T>(SomeType<T> some) { }
public void Add<T>(AnotherType<T> another) { }
Run Code Online (Sandbox Code Playgroud)
如何通过反射找到每种方法?例如,如何Add<T>(SomeType<T> some)通过反射获得方法?你能帮我吗?提前致谢.
C#/ CIL/Reflection.Emit问题:
我正在尝试定义一个具有函数指针的类型,实例化该类型,在另一个类型上创建静态方法(因为我不知道如何使"只是一个函数"),给出一个指向这个静态方法的指针到实例,然后使用该指针调用该函数.
我收效甚微.:-(
这是类型:
Thunk = modb.DefineType("Thunk");
Thunk.DefineField("Env" , Env.AsType(), FieldAttributes.Public);
Thunk.DefineField("Expr", typeof(int), FieldAttributes.Public); // int is the correct type according to http://msdn.microsoft.com/en-us/library/system.reflection.emit.opcodes.ldftn.aspx
Thunk.CreateType();
Run Code Online (Sandbox Code Playgroud)
到目前为止这么好(我想).然后我创建其中一个人并分配函数指针:
var methodBuilder = MainType.DefineMethod("my_other_little_function", MethodAttributes.Static, typeof(Int64), new[] {Env.AsType()});
{
var il2 = methodBuilder.GetILGenerator();
il2.Emit(OpCodes.Ldarg_0);
il2.Emit(OpCodes.Stloc_0);
binding.Expr.Compile(il2);
il2.Emit(OpCodes.Ret);
}
il.Emit(OpCodes.Newobj, ThunkCtor);
il.Emit(OpCodes.Dup);
il.Emit(OpCodes.Ldloc_0);
il.Emit(OpCodes.Stfld, Thunk.GetField("Env"));
il.Emit(OpCodes.Dup);
il.Emit(OpCodes.Ldftn, methodBuilder);
il.Emit(OpCodes.Stfld, Thunk.GetField("Expr"));
Run Code Online (Sandbox Code Playgroud)
据我所知,这部分工作正常.当我尝试调用它时,问题出在其他地方:
var func = il.DeclareLocal(typeof(int));
il.Emit(OpCodes.Dup);
il.Emit(OpCodes.Ldfld, Thunk.GetField("Expr"));
il.Emit(OpCodes.Stloc, func);
il.Emit(OpCodes.Ldfld, Thunk.GetField("Env"));
il.Emit(OpCodes.Ldloc, func);
il.EmitCalli(OpCodes.Calli, CallingConventions.Standard, typeof(Int64), new[] { Env.AsType() }, null);
Run Code Online (Sandbox Code Playgroud)
如果我尝试运行由此创建的程序,我会在执行任何字节码之前得到错误(或者至少它是如何出现的):
Unhandled Exception: …Run Code Online (Sandbox Code Playgroud) 我有两个功能:
public void DeleteRecord(int id);public T DeleteRecord<T>(int id);以下是我尝试动态调用泛型方法的方法:
MethodInfo method = typeof(DAL).GetMethod("DeleteRecord", new[] { typeof(int) });
MethodInfo generic = method.MakeGenericMethod(returnType);
object o = generic.Invoke(null, new object[] { dbname, spname, expandoAsDictionary });
Run Code Online (Sandbox Code Playgroud)
第一行抛出异常,因为它找到了一个模糊的定义.有没有办法可以获得MethodInfo泛型方法而不使用GetMethods和循环查询结果IsGenericMethod?
编辑:请删除'复制',因为两个建议的答案要么用内循环解决这个问题(GetMethods().选择...)或者甚至不解决重载问题.
我希望创建一个自定义属性来抑制在C#中执行方法,即使它被调用.例如,在下面的代码块中,如果方法具有"跳过"属性,即使从Main调用它也不应该执行.
public class MyClass {
public static void main()
{
aMethod();
}
[Skip]
public void aMethod() {
..
}
}
Run Code Online (Sandbox Code Playgroud)
如何使用C#中的反射来实现这一目标?
在下面的代码片段中,我设法提取了带有Skip属性的方法,我无法弄清楚如何阻止它们执行!
MethodInfo[] methodInfos = typeof (MyClass).GetMethods();
foreach (var methodInfo in methodInfos)
{
if (methodInfo.HasAttribute(typeof(SkipAttribute)))
{
// What goes here ??
}
}
Run Code Online (Sandbox Code Playgroud)
我们非常欢迎任何有正确方向的帮助或建议:)
public abstract class BaseAspectAttribute : Attribute
{
protected internal virtual void OnMethodBeforeExecuting(object args)
{
Console.WriteLine("Base Attribute OnMethodBeforeExecuting Work");
}
}
public class LogAttribute : BaseAspectAttribute
{
protected override void OnMethodBeforeExecuting(object args)
{
Console.WriteLine("Log Attribute OnMethodBeforeExecuting Work");
}
}
Run Code Online (Sandbox Code Playgroud)
我尝试在LogAttribute =>中获取方法
object[] customAttributesOnMethod = methodInfo.GetCustomAttributes(typeof (BaseAspectAttribute), true);
foreach (object attribute in customAttributesOnMethod)
{
MethodInfo[] methodsInSelectedAttribute = attribute.GetType().GetMethods();
}
Run Code Online (Sandbox Code Playgroud)
如何在LogAttribute中获取受保护的覆盖方法?
var className = typeof(Console);
var methodInfo = className.GetMethod("WriteLine",new [] { typeof(string) });
Run Code Online (Sandbox Code Playgroud)
我有一个Writel方法的methodInfo对象,现在如果我们看到该方法的定义,它看起来像这样.
//
// Summary:
// Writes the specified string value, followed by the current line terminator,
// to the standard output stream.
//
// Parameters:
// value:
// The value to write.
//
// Exceptions:
// System.IO.IOException:
// An I/O error occurred.
public static void WriteLine(string value);
Run Code Online (Sandbox Code Playgroud)
我想要的是得到一个特定方法的评论.,有什么办法可以用反射实现这个目的吗?或任何其他可能的方式?
首先我举一个我知道答案的简单例子。考虑:
class Animal
{
public virtual void M() { Console.WriteLine("a"); }
}
class Giraffe : Animal
{
public override void M() { Console.WriteLine("g"); }
}
Run Code Online (Sandbox Code Playgroud)
然后某处代码:
var am = typeof(Animal).GetMethod("M");
var gm = typeof(Giraffe).GetMethod("M");
Console.WriteLine(am == gm); // False
Console.WriteLine(am == gm.GetBaseDefinition()); // True
Run Code Online (Sandbox Code Playgroud)
我们看到这am和gm不被认为是平等的,这是完全公平的(后者是对前者的覆盖)。但是,通过最后一行我们可以确定这两种方法是相关的;一个是另一个的“基本方法”。
(您甚至可以检查引用是否相等,(object)am == (object)gm.GetBaseDefinition(),您仍然会得到 True。)
现在对于我有一个问题的情况。考虑一下:
class Plant
{
public void N() /* non-virtual */ { }
}
class Tree : Plant
{
}
Run Code Online (Sandbox Code Playgroud)
和:
var pn = typeof(Plant).GetMethod("N");
var …Run Code Online (Sandbox Code Playgroud) methodinfo ×10
c# ×9
reflection ×8
.net ×3
generics ×2
aop ×1
caching ×1
cil ×1
delegates ×1
inheritance ×1
metadata ×1