Changing callvirt to call in IL - c#

During some experiments with IL, I attempted to change callvirt calls in an assembly to call methods. Basically what happens is that I have an inheritance chain with member functions that I am calling.
Basically the call is similar to this:
((MyDerivedClass)myBaseObject).SomeCall();
or in IL
castclass MyDerivedClass // ** 1
call SomeCall() // ** 2
The base class defines SomeCall as abstract method, the derived class implements it. The derived class is sealed.
I know that callvirt is basically the equivalent of check if the object is null, if it's not call the method using the vtable and if it is, throw an exception. In my case I know that it's never null and I know that's the implementation I want to call. I understand why you would normally need a callvirt in such a case.
That said, because I know that the object is never null, and always is an instance of the derived type, I would think it's not a problem:
When you consider that data and types are separated, I'd actually figure that (**1) could be removed (the data of the object will be the same) and
That (**2) can be a simple call, since we know exactly what member to call. No vtable lookup is necessary.
It also seemed to me like a quite reasonable thing the compiler can also deduce in some cases. For those interested, yes, there is a speed penalty for callvirt, although it's pretty small.
However. PEVerify tells me it's wrong. And as a good boy, I always take note of what PEVerify is telling me. So what am I missing here? Why does changing this call lead to an incorrect assembly?
Apparently creating a minimum test case isn't so simple... so far I don't have a lot of luck with it.
As for the issue itself, I can simply reproduce it in a larger program:
[IL]: Error: [C:\tmp\emit\test.dll : NubiloSoft.Test::Value][offset 0x00000007] The 'this' parameter to the call must be the calling method's 'this' parameter.
IL code of Value:
L_0000: ldarg.0
L_0001: ldfld class NubiloSoft.Test SomeField
L_0006: ldarg.1
L_0007: call instance bool NubiloSoft.Test::Contains(int32)
The type of the field is NubiloSoft.Test.
As for Contains, it's abstract in a base class, and in the derived class it's overridden. Just as you would expect. When I remove the 'abstract base method' + 'override', PEVerify likes it all again.
In an attempt to reproduce the issue I did this, so far without luck to reproduce it in a minimal test case:
public abstract class FooBase
{
public abstract void MyMethod();
}
// sealed doesn't seem to do anything...
public class FooDerived : FooBase
{
public override void MyMethod()
{
Console.WriteLine("Hello world!");
}
}
public class FooGenerator
{
static void Main(string[] args)
{
Type t = CreateClass();
object o = Activator.CreateInstance(t, new[] { new FooDerived() });
var meth = t.GetMethod("Caller");
meth.Invoke(o, new object[0]);
Console.ReadLine();
}
public static Type CreateClass()
{
// Create assembly
var assemblyName = new AssemblyName("testemit");
var assemblyBuilder =
AppDomain.CurrentDomain.DefineDynamicAssembly(assemblyName,
AssemblyBuilderAccess.RunAndSave, #"c:\tmp");
// Create module
var moduleBuilder = assemblyBuilder.DefineDynamicModule("testemit", "test_emit.dll", false);
// Create type : IFoo
var typeBuilder = moduleBuilder.DefineType("TestClass", TypeAttributes.Public, typeof(object));
// Apparently we need a field to trigger the issue???
var field = typeBuilder.DefineField("MyObject", typeof(FooDerived), FieldAttributes.Public);
ConstructorBuilder constructorBuilder = typeBuilder.DefineConstructor(
MethodAttributes.Public | MethodAttributes.HideBySig |
MethodAttributes.SpecialName | MethodAttributes.RTSpecialName,
CallingConventions.HasThis, new Type[] { typeof(FooDerived) });
// Generate the constructor IL.
ILGenerator gen = constructorBuilder.GetILGenerator();
// The constructor calls the constructor of Object
gen.Emit(OpCodes.Ldarg_0);
gen.Emit(OpCodes.Call, typeof(object).GetConstructor(Type.EmptyTypes));
// Store the field
gen.Emit(OpCodes.Ldarg_0);
gen.Emit(OpCodes.Ldarg_1);
gen.Emit(OpCodes.Stfld, field);
// Return
gen.Emit(OpCodes.Ret);
// Add the 'Second' method
var mb = typeBuilder.DefineMethod("Caller",
MethodAttributes.HideBySig | MethodAttributes.NewSlot | MethodAttributes.Virtual |
MethodAttributes.Final | MethodAttributes.Public, CallingConventions.HasThis,
typeof(void), Type.EmptyTypes);
// Implement
gen = mb.GetILGenerator();
gen.Emit(OpCodes.Ldarg_0);
gen.Emit(OpCodes.Ldfld, field);
gen.Emit(OpCodes.Call, typeof(FooDerived).GetMethod("MyMethod"));
gen.Emit(OpCodes.Ret);
Type result = typeBuilder.CreateType();
assemblyBuilder.Save("testemit.dll");
return result;
}
}
When you run it and call peverify, it'll tell you the code doesn't have bugs... :-S
I'm not sure what's going on here... seems to me like it's pretty similar.

I suspect this blog post is relevant. In particular:
Some consider this a violation of privacy through inheritence. Lots of code is written under the assumption that overriding a virtual method is sufficient to guarantee custom logic within gets called. Intuitively, this makes sense, and C# lulls you into this sense of security because it always emits calls to virtual methods as callvirts.
And then:
Late in Whidbey, some folks decided this is subtly strange enough that we at least don’t want partially trusted code to be doing it. That it’s even possible is often surprising to people. We resolved the mismatch between expectations and reality through the introduction of a new verification rule.
The rule restricts the manner in which callers can make non-virtual calls to virtual methods, specifically by only permitting it if the target method is being called on the caller’s ‘this’ pointer. This effectively allows an object to call up (or down, although that would be odd) its own type hierarchy.
In other words, assuming this change is what you're talking about (it sounds like it) the rule is there to prevent IL from violating normal expectations of how virtual methods are called.
You might want to try making the SomeCall method sealed in MyDerivedClass... at that point it's not virtual any more in the sense that a call to SomeCall on a reference of type MyDerivedClass will always call the same method... whether that's sufficiently non-virtual for peverify is a different matter though :)

Related

ResolveMethod() Returning Completely Different Method

I was resolving methods from .NET DLLs, and noticed that the method being returned by Module.ResolveMethod() is completely different from original method. I am specifying the method's exact MetadataToken, so it makes absolutely no sense to me why I would end up with anything else but the original method.
In the below example, I have the 'Dispose()' method. I grab its metadata token and resolve it, only to find that I now have the 'OnBackColorChanged(System.EventArgs)'method
static void Main(string[] args)
{
Assembly assembly = Assembly.LoadFrom(#"C:\Windows\Microsoft.NET\Framework\v4.0.30319\System.Windows.Forms.dll");
MethodInfo method = assembly.GetModules()[0].GetTypes()[300].GetMethods()[362];
Console.WriteLine(method); //Returns 'Void Dispose()'
MethodInfo method2 = (MethodInfo)assembly.GetModules()[0].ResolveMethod(method.MetadataToken);
Console.WriteLine(method2); //Returns 'Void OnBackColorChanged(System.EventArgs)' ...why?
}
Button, through long inheritance chain, inherits from Component class, which implements IDisposable and has void Dispose() method. This is the method you obtain via
assembly.GetModules()[0].GetTypes()[300].GetMethods()[362];
Since this method is declared on type Component, which is located in System assembly - no surprise that using its metadata handle to resolve method from completely different module (System.Windows.Forms) leads to random results.
If you want to get only methods declared on this concrete type - use BindingFlags.DeclaredOnly:
var allMethods = type.GetMethods(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly);
But note this will return only methods declared on Button, not on any parent type, even if that parent type belongs to the same module.
Alternatively - filter by module:
Assembly assembly = Assembly.LoadFrom(#"C:\Windows\Microsoft.NET\Framework\v4.0.30319\System.Windows.Forms.dll");
var module = assembly.GetModules()[0];
var type = module.GetTypes()[300];
var allMethods = type.GetMethods().Where(c => c.Module == module).ToArray();

Calling function from ComImport class doesn't fail as expected

I'm trying to verify that the class I'm trying to use via COM works as expected. Unfortunately it seems to succeed on a call which should fail:
enum X509CertificateEnrollmentContext
{
ContextUser = 0x1,
ContextMachine = 0x2,
ContextAdministratorForceMachine = 0x3
}
[ComImport(), Guid("884e2045-217d-11da-b2a4-000e7bbb2b09")]
class Cenroll { }
[Guid("728ab35d-217d-11da-b2a4-000e7bbb2b09")]
interface IX509CertificateRequestCmc2
{
void InitializeFromTemplate(
[In] X509CertificateEnrollmentContext Context,
[In] IX509EnrollmentPolicyServer pPolicyServer,
[In] IX509CertificateTemplate pTemplate);
}
static void Main(string[] args)
{
var cr = new Cenroll();
var cmc2 = (IX509CertificateRequestCmc2)cr;
cmc2.InitializeFromTemplate(X509CertificateEnrollmentContext.ContextUser, null, null);
}
Casting from Cenroll to the interface works, which indicates that the guids are ok. (and it fails casting to other guids, so it's not random success)
But when I call InitializeFromTemplate, with both parameters set to null, it succeeds. The documentation says that the result should be an E_POINTER error:
Return code - Description
E_POINTER - The pPolicyServer and pTemplate parameters cannot be NULL.
So why don't I see an exception?
The problem is that you are redeclaring the interface, and the new definition is different from the original.
Guids are OK, but underneath, QueryInterface implementation checks GUID, and returns the pointer to the implementation - this is the interface vtable and method addresses are calculated relative to this address (when a call to the method is compiled, offset of the method is added to this address to get the actuall address).
In your implementation, InitializeFromTemplate is the first method and generated client code calls the method at the beginning of vtable.
However, in the original interface, there are 56 other methods before InitializeFromTemplate because there is an inheritance chain:
IX509CertificateRequest (25 methods)
|
+-> IX509CertificateRequestPkcs7 (8 methods)
|
+-> IX509CertificateRequestCmc (23 methods)
|
+-> IX509CertificateRequestCmc2
Function addresses in the certenroll.dll adhere to this layout, so when you call InitializeFromTemplate as declared in your interface, you are calling the first method in chain which is actually IX509CertificateRequest::Initialize.
As an experiment, if you add 56 dummy methods before InitializeFromTemplate in your IX509CertificateRequestCmc2 you will correctly receive an exception:
[Guid("728ab35d-217d-11da-b2a4-000e7bbb2b09")]
interface IX509CertificateRequestCmc
{
void fn1();
void fn2();
...
void fn56();
void InitializeFromTemplate(...);
}
The call will throw: CertEnroll::CX509CertificateRequestCmc::InitializeFromTemplate: Invalid pointer 0x80004003 (-2147467261)
Of course, the solution is not to add the dummy methods :) You should use the generated interop types instead of providing your own. As you are referencing the certenroll assembly, I don't understand why don't you simply use those generated interop classes. Here's the full example which behaves as expected:
using CERTENROLLLib;
namespace comcerttest
{
class Program
{
static void Main(string[] args)
{
// If you are embedding the interop types, note that you must
// remove the `Class` suffix from generated type name in order
// to instantiate it. See link at the bottom for explanation:
var cr = new CX509CertificateRequestCmc();
var cmc2 = (IX509CertificateRequestCmc2)cr;
cmc2.InitializeFromTemplate(X509CertificateEnrollmentContext.ContextUser, null, null);
}
}
}
The issue with using class vs interface type is explained here:
Using embedded interop types

Why does adding beforefieldinit drasticly improve the execution speed of generic classes?

I'm working on a proxy and for generic classes with a reference type parameter it was very slow. Especially for generic methods (about 400 ms vs 3200 ms for trivial generic methods that just returned null). I decided to try to see how it would perform if I rewrote the generated class in C#, and it performed much better, about the same performance as my non-generic class code.
Here is the C# class I wrote:: (note I changed by naming scheme but not a heck of a lot)::
namespace TestData
{
public class TestClassProxy<pR> : TestClass<pR>
{
private InvocationHandler<Func<TestClass<pR>, object>> _0_Test;
private InvocationHandler<Func<TestClass<pR>, pR, GenericToken, object>> _1_Test;
private static readonly InvocationHandler[] _proxy_handlers = new InvocationHandler[] {
new InvocationHandler<Func<TestClass<pR>, object>>(new Func<TestClass<pR>, object>(TestClassProxy<pR>.s_0_Test)),
new GenericInvocationHandler<Func<TestClass<pR>, pR, GenericToken, object>>(typeof(TestClassProxy<pR>), "s_1_Test") };
public TestClassProxy(InvocationHandler[] handlers)
{
if (handlers == null)
{
throw new ArgumentNullException("handlers");
}
if (handlers.Length != 2)
{
throw new ArgumentException("Handlers needs to be an array of 2 parameters.", "handlers");
}
this._0_Test = (InvocationHandler<Func<TestClass<pR>, object>>)(handlers[0] ?? _proxy_handlers[0]);
this._1_Test = (InvocationHandler<Func<TestClass<pR>, pR, GenericToken, object>>)(handlers[1] ?? _proxy_handlers[1]);
}
private object __0__Test()
{
return base.Test();
}
private object __1__Test<T>(pR local1) where T:IConvertible
{
return base.Test<T>(local1);
}
public static object s_0_Test(TestClass<pR> class1)
{
return ((TestClassProxy<pR>)class1).__0__Test();
}
public static object s_1_Test<T>(TestClass<pR> class1, pR local1) where T:IConvertible
{
return ((TestClassProxy<pR>)class1).__1__Test<T>(local1);
}
public override object Test()
{
return this._0_Test.Target(this);
}
public override object Test<T>(pR local1)
{
return this._1_Test.Target(this, local1, GenericToken<T>.Token);
}
}
}
This is compiles in release mode to the same IL as my generated proxy here is the class that its proxying::
namespace TestData
{
public class TestClass<R>
{
public virtual object Test()
{
return default(object);
}
public virtual object Test<T>(R r) where T:IConvertible
{
return default(object);
}
}
}
There was one-exception, I was not setting the beforefieldinit attribute on the type generated. I was just setting the following attributes::public auto ansi
Why did using beforefieldinit make the performance improve so much?
(The only other difference was I wasn't naming my parameters which really didn't matter in the grand scheme of things.
The names for methods and fields are scrambled to avoid collision with real methods.
GenericToken and InvocationHandlers are implementation details that are irrelevant for sake of argument.
GenericToken is literally used as just a typed data holder as it allows me to send "T" to the handler
InvocationHandler is just a holder for the delegate field target there is no actual implementation detail.
GenericInvocationHandler uses a callsite technique like the DLR to rewrite the delegate as needed to handle the different generic arguments passed
)
EDIT::
Here is the test harness::
private static void RunTests(int count = 1 << 24, bool displayResults = true)
{
var tests = Array.FindAll(Tests, t => t != null);
var maxLength = tests.Select(x => GetMethodName(x.Method).Length).Max();
for (int j = 0; j < tests.Length; j++)
{
var action = tests[j];
Stopwatch sw = Stopwatch.StartNew();
for (int i = 0; i < count; i++)
{
action();
}
sw.Stop();
if (displayResults)
{
Console.WriteLine("{2} {0}: {1}ms", GetMethodName(action.Method).PadRight(maxLength),
((int)sw.ElapsedMilliseconds).ToString(), j);
}
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
}
}
private static string GetMethodName(MethodInfo method)
{
return method.IsGenericMethod
? string.Format(#"{0}<{1}>", method.Name, string.Join<Type>(",", method.GetGenericArguments()))
: method.Name;
}
And in a test I do the following::
Tests[0] = () => proxiedTestClass.Test();
Tests[1] = () => proxiedTestClass.Test<string>("2");
Tests[2] = () => handClass.Test();
Tests[3] = () => handClass.Test<string>("2");
RunTests(100, false);
RunTests();
Where Tests is a Func<object>[20], and proxiedTestClass is the class generated by my assembly, and handClass is the one I generated by hand.
RunTests is called twice, once to "warm" things up, and again to run it and print to the screen. I mostly took this code from a post here by Jon Skeet.
As stated in ECMA-335 (CLI cpecification), part I, section 8.9.5:
The semantics of when and what triggers execution of such type
initialization methods, is as follows:
A type can have a type-initializer method, or not.
A type can be specified as having a relaxed semantic for its type-initializer method (for convenience below, we call this relaxed
semantic BeforeFieldInit).
If marked BeforeFieldInit then the type’s initializer method is executed at, or sometime before, first access to any static field
defined for that type.
If not marked BeforeFieldInit then that type’s initializer method is executed at (i.e., is triggered by):
a. first access to any static field of that type, or
b. first invocation of any static method of that type, or
c. first invocation of any instance or virtual method of that type
if it is a value type or
d. first invocation of any constructor for that type.
Also, as you can see from the Michael's code above, the TestClassProxy has only one static field: _proxy_handlers. Notice, that it is used only two times:
In the instance constructor
And in the static field initializer itself
So when BeforeFieldInit is specified, type-initializer will be called only once: in the instance constructor, right before the first access to _proxy_handlers.
But if BeforeFieldInit is omitted, CLR will place the call to the type-initializer before every TestClassProxy's static method invocation, static field access, etc.
In particular, the type-initializer will be called on every invocation of s_0_Test and s_1_Test<T> static methods.
Of course, as stated in ECMA-334 (C# Language Specification), section 17.11:
The static constructor for a non-generic class executes at most once
in a given application domain. The static constructor for a generic
class declaration executes at most once for each closed constructed
type constructed from the class declaration (§25.1.5).
But in order to guarantee this, CLR have to check (in a thread-safe manner) if the class is already initialized, or not.
And these checks will decrease the performance.
PS: You might be surprised that performance issues will gone once you change s_0_Test and s_1_Test<T> to be instance-methods.
First, if you want to learn more about beforefieldinit, read Jon Skeet's article C# and beforefieldinit. Parts of this answer are based on that and I'll repeat the relevant bits here.
Second, your code does very little, so overhead will have significant impact on your measurements. In real code, the impact is likely to be much smaller.
Third, you don't need to use Reflection.Emit to set whether a class has beforefieldint. You can disable that flag in C# by adding a static constructor (e.g. static TestClassProxy() {}).
Now, what beforefieldinit does is that it governs when is the type initializer (method called .cctor) called. In C# terms, type initializer contains all static field initializers and code from the static constructor, if there is one.
If you don't set that flag, the type initializer will be called when either an instance of the class is created or any of the static members of the class are referenced. (Taken from the C# spec, using CLI spec here would be more accurate, but the end result is the same.*)
What this means is that without beforefieldinit, the compiler is very confined about when to call the type initializer, it can't decide to call it a bit earlier, even if doing that would be more convenient (and resulted in faster code).
Knowing this, we can look at what's actually happening in your code. The problematic cases are static methods, because that's where the type initializer might be called. (Instance constructor is another one, but you're not measuring that.)
I focused on the method s_1_Test(). And because I don't actually need it to do anything, I simplified it (to make the generated native code shorter) to:
public static object s_1_Test<T>(TestClass<pR> class1, pR local1) where T:IConvertible
{
return null;
}
Now, let's look at the disassembly in VS (in Release mode), first without the static constructor, that is with beforefieldinit:
00000000 xor eax,eax
00000002 ret
Here, the result is set to 0 (it's done in somewhat obfuscated manner for performance reasons) and the method returns, very simple.
What happens with static the static constructor (i.e. without beforefieldinit)?
00000000 sub rsp,28h
00000004 mov rdx,rcx
00000007 xor ecx,ecx
00000009 call 000000005F8213A0
0000000e xor eax,eax
00000010 add rsp,28h
00000014 ret
This is much more complicated, the real problem is the call instruction, which presumably calls a function that invokes the type initializer if necessary.
I believe this the source of the performance difference between the two situations.
The reason why the added check is necessary is because your type is generic and you're using it with a reference type as a type parameter. In that case, the JITted code for different generic versions of your class is shared, but the type initializer has to be called for each generic version. Moving the static methods to another, non-generic type would be one way to solve the issue.
* Unless you do something crazy like calling instance method on null using call (and not callvirt, which throws for null).

How can I instantiate a COM class interface generically

I'm trying to refactor a piece of code and ran out of options I can think off.
This is the original code I had:
if (WebConfigSettings.ComPartition == null && HttpContext.Current != null)
Nses = new NSession();
else
Nses = (INSession)Marshal.BindToMoniker(string.Format("partition:{0}/new:NuntioServer.NSession", WebConfigSettings.ComPartition));
AND
if (WebConfigSettings.ComPartition == null && HttpContext.Current != null)
apses.Wses = new WSession();
else
apses.Wses = (IWSession)Marshal.BindToMoniker(string.Format("partition:{0}/new:NuntioServer.WSession", WebConfigSettings.ComPartition));
And this is how I'm trying to refactor it:
(Yes, in C# you can instantiate an interface.)
public static TInterface Get<TSubInterface, TInterface>() where TSubInterface: TInterface
{
<snip></snip>
if (!useComPartitions)
return Activator.CreateInstance<TSubInterface>(); // --> this is not cooperating
return (TInterface)Marshal.BindToMoniker(.....);
}
Here's what I already tried:
I tried specifying the new() constraint and then doing a 'new TSubInterface()':
this results in a build error: "..must be a non-abstract type with a public parameterless constructor in order to use it as parameter 'TSubInterface' in the generic type or method.."
when I use Activator.CreateInstance, I get a runtime exception: "Cannot create an instance of an interface"
when I use Activator.CreateComInstanceFrom("someAssemblyName", "typeName"), I get a compilation error: "Cannot convert expression type 'System.Runtime.Remoting.ObjectHandle' to return type TInterface"
[edit] I was able to make this compile by adding 'where TSubInterface : class, but I'm not sure if that makes sense, since TSubInterface is an interface.
Using CreateComInstanceFrom also doesn't work, because it's trying to find the assembly which is specified in a directory where that dll is not and should not be.
Can I somehow make this compile and run?
You'll need to focus on the seeming magic of being able to create a class object from an interface name. Let's pick an example that everybody can try. Create a new console application and use Project + Add Reference, Browse tab and select c:\windows\system32\shell32.dll.
Have a look at the interop library that generates with Object Browser. Note how the Shell type is an interface type. Now write this code:
class Program {
static void Main(string[] args) {
var shl = new Shell32.Shell();
}
}
Compile and run ildasm.exe on the .exe file. You'll see:
.method private hidebysig static void Main(string[] args) cil managed
{
.entrypoint
// Code size 8 (0x8)
.maxstack 1
.locals init ([0] class [Interop.Shell32]Shell32.Shell 'shl')
IL_0000: nop
IL_0001: newobj instance void [Interop.Shell32]Shell32.ShellClass::.ctor()
IL_0006: stloc.0
IL_0007: ret
} // end of method Program::Main
Note how the type name got substituted from Shell to ShellClass. The type library importer created that class, it uses the original coclass name and append "Class" to the name. The compiler makes that substitution.
Which is the key, Activator.CreateInstance() is not able to make that same substitution. I don't see an obvious way to have generics make that same substitution, beyond directly using the IFooClass name instead of the interface name. Technically you can retrieve the [CoClass] attribute that the type library importer applied to the interface type.
It can be done by figuring out what's the coClass of that interface and creating an instance of that:
var coClassAttribute = type.GetCustomAttribute<CoClassAttribute>(); // our extension method
return (TSubInterface)Activator.CreateInstance(coClassAttribute.CoClass);
I am not satisfied with this, but it works.
(won't mark this as the correct answer)

Push and pull value on callstack .net

I've done this before, so I know it can be done..(although badly documented) but forgot how. I've been searching for 2 hours now and can't find anything like it.
I want to push and pull values on the callstack, like so:
public void Method1()
{
InsertMagicClassHere.Push("Key", 1);//or something
Method2();
}
public void Method2()
{
int value = InsertMagicClassHere.Pull("Key");//or something
}
I need this parameter in nearly all my methods for logging.. and don't want to pass this 3 layers deep with arguments.
You are looking for Reflection.Emit; however, this is not how it works.
You can't really emit inline opcodes.
Instead, you can emit whole methods/classes and load them as 'temporary' assemblies. You then call into the emitted method.
Obligatory sample:
public void CreateMethod()
{
AppDomain currentDomain = AppDomain.CurrentDomain;
AssemblyBuilder asmbuilder = this.GetAssemblyBuilder("MyAssembly");
ModuleBuilder mbuilder = this.GetModule(asmbuilder);
TypeBuilder tbuilder = this.GetTypeBuilder(mbuilder, "MyClass");
Type[] tparams = { typeof(System.Int32), typeof(System.Int32) };
MethodBuilder methodSum = this.GetMethod(tbuilder, "Sum", typeof(System.Single),
tparams);
ILGenerator generator = methodSum.GetILGenerator();
generator.DeclareLocal(typeof(System.Single));
generator.Emit(OpCodes.Ldarg_1);
generator.Emit(OpCodes.Ldarg_2);
generator.Emit(OpCodes.Add_Ovf);
generator.Emit(OpCodes.Conv_R4);
generator.Emit(OpCodes.Stloc_0);
generator.Emit(OpCodes.Ldloc_0);
generator.Emit(OpCodes.Ret);
}
So what you could do
take an existing method
disassemble it
write the code to emit a new method on the IL level (using Reflection.Emit)
load the emitted assembly
call into your code.
See these articles for good starters:
http://www.codeproject.com/KB/cs/DLR.aspx
MSDN: using Reflection Emit
Okay. the answer is:
CallContext
This works:
public void Method1()
{
CallContext.SetData("Key", 1);
Method2();
}
public void Method2()
{
int value = (int)CallContext.GetData("Key");
}
Like I said this is not a well known feature.. If you knew it, you would have known what I was referring to.
I think it's a cool feature, not many uses for it, but still..

Categories