Im looking for something that can compile a method as if it was in a different class so that i can Inject a method that uses internal fields and types without having to manually change the Operand values.
For instance if we need to get a value for debugging:
class bla{
internal string importantValue;
...
public void onInitialize(){
...
//this is where the compiler should be made to think it is
}
}
and the code that goes into the compiler
public void onInitialize(){ //code to be compiled as if it were in that method
File.WriteAllText("usefulString.txt",importantValue.toString());
}
and then we can get the il of the compiled output and insert it into bla.onInitialize so that we now can get our value
With the example given, making onInitialize() protected, then constructing an override in another class would work.
Alternatively make the body of the method a delegate defined at class level - then set a different delegate in your code to make it do something else.
I really don't get what you want to achive and I think there is a simpler way.
But if I understand from your question title, you want to compile your class bla (for example) and you want that in method onInitialize will be added new code (that doesn't exit there) in compile time. It it true?
For this you have a several ways. I'll describe two of them.
You can use library like StaticProxy.Fody. This lib let you intercept method and inject into it whatever you want. So in your example, you intercept onInitialize method and you add to it this code File.WriteAllText("usefulString.txt",importantValue.toString());
All of this in compile time. After you compile the code your ouput dll will contain this injected code.
Second option is to compile your code regulary and after that you can use Mono.Cecil to read your compiled dll and write code that will add whatever you want to where you want, (in our example, add File.WriteAllText etc. to onInitialize) after you save this dll it will contain the new injected code.
Both of the options are simple way to add code in static manner (aka compile time and not runtime).
Related
Say I have a class (shown as meta data) -- code lies in dll:
class Foo : IA, IB, IC, ID...
{
public void Bar(); // implementation
}
I would like to know where this Bar method was declared -- in IA, or IB, or... ... or it is fresh implementation -- without referring to any external sources like MSDN.
Can I do this in Visual Studio? If yes -- how?
If this was editable file (like my own code) this would be easy -- simply comment out for a while this method and see which interface becomes flagged.
If you are looking to get the source code of any .dll file you cannot do it with Visual Studio, But you can make use of decompiler tools like JustDecomplie , dotPeek etc
But even with these decompilers it is not guaranteed to get back the source code 100% accurately.
Remove the word public from the method and put, one at a time, IA. and all the other interfaces in front of the method name, then try to compile.
void IA.Bar() {
}
Note that more than one interface may have this method so you can try them all, or just paste in one copy of the method for each interface and see which ones work.
(This, by the way, is how you make different implementations for methods with the same name and signature from two different interfaces. I had to do this the other day with an indexer that one interface expected to be read-only and the other read/write. When the object is cast to one of the interfaces it uses the corresponding method.)
Alternately, ReSharper can do this for you. Simply hover over the method name with Resharper on.
I've recently had to make a forray into decompiling a colleague's code while they're away, and found that most of it looks surprisingly nice (thanks ILSpy), with the notable exception of a couple of places where we needed to use dynamic - these got mangled into several parts:
A call site container - i.e. what resembles a class in definition, but let's say the method in which dynamic was used was DoStuff, would have a declaration along the lines of public /* static? I forget */ class <DoStuff>CallSiteContainer_Plus_Some_Weirdness { /* bunch of CallSite fields */ }
A lot of code that checks whether various CallSites within the container have been assigned and assigns them before usage as required using approaches I really don't get yet.
My question is regarding the syntax of the class declaration in the 1st point. It looks like a generic class, but it clearly isn't. Can anyone explain what's going on there?
Please note, I'm not looking for help in working out the original code - I've already managed to do that by judicious use of find and replace, and breaking out the autogenerated code from everything else. But I'd like to understand how the CallSite container syntax is a valid class name!
Here's an example of such auto-generated class:
private static class <>o__0
{
public static CallSite<Action<CallSite, Type, object>> <>p__0;
}
If you are worried about the <>o__0 class name and the <>p__0 field name, then you are right, those are not valid C# names but this doesn't mean that they are not valid IL names which is what the compiler generates. The reason why it uses such special symbols is to ensure that they will never conflict with class names that you as a developer might have written.
Say I have these files:
MyCode.cs
namespace MyCodeNamespace
{
public class MyClass
{
//OMITTED
}
internal static class MyExtensions
{
internal static void Foo(this string str)
{
//OMITTED
}
}
}
OtherCode.cs
using MyCodeNamespace;
namespace OtherCodeNamespace
{
//OMITTED
}
The two files are part of the same assembly. Is there any way I can make Foo accessible to MyCode.cs but not to OtherCode.cs? My question is similar to this question:
C# Extension Methods only visible and accessible within one class ("private")
But its accepted answer isn't really what I'm looking for. I want to make an extension method that's only visible to the code I'm working on, and according to the answer to the above question, someone could still access it by adding a "using" statement. Is there a way I can create an extension method that is only visible to my code, and nowhere else, not even by another class in the same assembly?
I ask because the syntax for calling an extension method is handy and would be useful for what I'm working on (otherwise I'd just create a private method instead), but I don't want others to see it and use it from their code in case it doesn't do what they assume it does. And thanks to Visual Studio's intellisense, my extension methods are currently showing up in the list of available methods (along with the option to add the namespace they're in).
There is no such thing as a namespace-limited access modifier in the .NET platform. From the docs
public : Access is not restricted.
protected : Access is limited to the containing class or types derived from the containing class.
Internal : Access is limited to the current assembly.
protected internal: Access is limited to the current assembly or types derived from the containing class.
private : Access is limited to the containing type.
That's all you have to work with. So the answer is no.
Extension methods are just semantic sugar that compile to the same IL as calling the static helpers directly.
MyExtensionMethods.DoSomething(myObject);
myObject.DoSomething();
You cannot restrict it from being called, but you can remove its visibility from Intellisense.
Simply move your extension methods to a different namespace, add a using statement in your MyCode.cs and don't include that namespace in OtherCode.cs
[update]
If you really need to restrict the caller, you could try using reflection to determine and restrict, but this is a bit overkill. Best to simply use a private static helper instead of doing this.
var frame = new System.Diagnostics.StackFrame(1, false);
var method = frame.GetMethod();
var type = method.DeclaringType;
// allow|deny type
I had a similar problem. I did not want the programmer to see my inner extension methods when configuring services in ASP.NET Core.
The solution for me was to add all extension methods to namespace Microsoft.Extensions.DependencyInjection that is used in Startup.cs and the user can see those methods. (As you would always do.)
If I wanted to "hide" something I added the extension method to MyNamespace.Extensions. If the user writes the correct name the helper for add using will show up but by default it won't be listed.
I know this is not a solution but might help someone.
think about similar thing;
c# assembly, friend assembly
will try InternalsVisibleTo;
if your classes is closed maybe will not helpfull but you can try it;
I'm new to .Net and I just saw this code that doesn't make sense to me (slightly abridged):
namespace test
{
public class sub : super
{
public sub(string text);
}
}
As you can see, there is a constructor that takes an argument, but does not implement a definition. How does that work? My guess is that it somehow relates to the super class, but I dont understand how, and I havent been able to find anything on Google.
Edit: Im running this in VS2010, and I just noticed that the tab has [from metadata] in the title. Perhaps this is why?
That's not code.
That's text that looks somewhat like code based on the metadata in the assembly. You'll see this when the IDE doesn't have access to the source code in question (For example, you press F12 on a method in a referenced assembly.) It provides the method signatures, properties, fields, etc from the types, without providing any of the actual implementation.
As written, the code you posted wouldn't even compile in C#.
If from the metadata, it's not going to show you the implementation of the methods.
It looks like code but it is text based on the metadata in the assembly. It means that the IDE is unable to access the source code in question.
I'm writing a set of unit tests for a large, complex class called ImageEditor from a piece of legacy code, where image processing and GUI functionality isn't strictly divided. One of the methods in the class, BaseImageChanged, seems to be concerned entirely with how images get displayed and should be disabled in my unit tests to avoid unnecessary complexity. The test project is in C#, and the original code is in VB; my idea was to create a Decorator for the class in C# and then hide the method behind an empty one that does nothing. However, when I try running the unit test, the VB code keeps referencing the old BaseImageChanged method as though the replacement didn't exist. Here's what I'm doing:
(VB class)
Public Class ImageEditor
...
Public Sub BaseImageChanged()
...
End Sub
...
End Class
(C# class)
class ImageEditorTestingClass : ImageEditor_Accessor
{
public new void BaseImageChanged() {}
}
Is there a way to accomplish this sort of interoperability, or will I have to find another way?
EDIT: The compiler error turned out to be a problem with reflection. Also, overriding the method didn't work as long as the base class was an accessor of ImageEditor instead of the original ImageEditor class.(No compiler error, but the base method's behavior wasn't overridden.)
Do you have access to the VB code? if so mark it virtual (C# syntax); Then in the C# code override it with an empty body so that id does nothing.
You should (almost) never use 'new' to redeclare methods or properties. If some code is assuming it's the base class, even if you pass a derived one, the base methods will be called.
For better understanding read about late-binding and early-binding in .NET
Early and late binding
It seems #estanford accepted this answer due to my comment below
"Where you call BaseImageChanged try using reflection"
I don't know VB at all, but this sounds more like a case for a virtual method with an override than a method hiding. The VB code is probably calling "this.BaseImageChanged()" somewhere, which wouldn't call your new method... right?
It looks like what's going on here is that
You have a library written in VB.Net
Your unit tests are written in C# and are using MSTest
You're trying to derive from the generated accessor instead of the original class
In this case the only option you have is to use new. The generated accessor class will not add virtual methods and hence if you want to provide an alternate method with the same name new is the only way to do so.