How to create an override method using Mono.Cecil? - mono.cecil

I'm using Mono.Cecil to generate an assembly that contains a derived class that overrides a specific method in an imported base class. The override method is an 'implicit' override. The problem is that I cannot figure out how to designate it as an override.
I'm using the following code to create the override method.
void CreateMethodOverride(TypeDefinition targetType,
TypeDefinition baseClass, string methodName, MethodInfo methodInfo)
{
// locate the matching base class method, which may
// reside in a different module
MethodDefinition baseMethod = baseClass
.Methods.First(method => method.Name.Equals(methodName));
MethodDefinition newMethod = targetType.Copy(methodInfo);
newMethod.Name = baseMethod.Name;
newMethod.Attributes = baseMethod.Attributes;
newMethod.ImplAttributes = baseMethod.ImplAttributes;
newMethod.SemanticsAttributes = baseMethod.SemanticsAttributes;
targetType.Methods.Add(newMethod);
}
It is my understanding that an implicit override must have the same signature as the inherited method. Using the above code, when I view the resulting method in Reflector, the base class and the derived class methods have the exact same signature, namely "public virtual void f(int param)".
I've tried removing the explicit "virtual" attribute, but then the derived method ends up as "public void f(int param)'.
How do I get the derived method to have the correct "public override void f(int param)" signature?
NOTE: I have an extension method ("TypeDefinition.Copy") that clones a MethodInfo and returns a MethodDefinition by importing all of the referenced types, etc.

In your base class, let's say you generate the following method:
public virtual void f(int);
You have to make sure that it has the flag IsVirtual set to true. You also have to make sure that it has the flag IsNewSlot = true, to make sure that it has a new slot in the virtual method table.
Now, for the overridden methods, you want to generate:
public override void f(int);
To do so, you also need to have the method to be IsVirtual, but also to tell it that it's not a new virtual method, but that it implicitly overrides another, so you have to make it .IsReuseSlot = true.
And because you're using implicit overriding, you also have to make sure both methods are .IsHideBySig = true.
With that all set, you should have a proper overriding method.

For the benefit of other readers, here is the final result obtained by following JB's answer:
void CreateMethodOverride(TypeDefinition targetType,
TypeDefinition baseClass, string methodName, MethodInfo methodInfo)
{
MethodDefinition baseMethod = baseClass
.Methods.First(method => method.Name.Equals(methodName));
MethodDefinition newMethod = targetType.Copy(methodInfo);
newMethod.Name = baseMethod.Name;
// Remove the 'NewSlot' attribute
newMethod.Attributes = baseMethod.Attributes & ~MethodAttributes.NewSlot;
// Add the 'ReuseSlot' attribute
newMethod.Attributes |= MethodAttributes.ReuseSlot;
newMethod.ImplAttributes = baseMethod.ImplAttributes;
newMethod.SemanticsAttributes = baseMethod.SemanticsAttributes;
targetType.Methods.Add(newMethod);
}

Related

Are private setters in C++/CX properties a thing?

Is it possible to create/design in a way to privately set a property but only expose the ability to get the properties to the consumers?
I've tackled a multiple inheritance property by making the base class wrapper a member of the concrete classes wrapper. I'd rather not allow someone to write over the base classes instance in the set of it's own property. But I can't seem to exclude set and set the base property and I can't make the set private.
Any ideas?
Code:
ConcreteClassWrapper(); // here I want to setup base class, i.e. give it a pointer to the actual C++ model I'm working with.
property BaseClassWrapper^ BaseClass
{
BaseClassWrapper^ get() { return baseClass; }
// I want to avoid giving my consumers the ability to set this property.
void set(BaseClassWrapper^ value) { baseClass= value; }
}
private:
BaseClassWrapper^ baseClass; // Having a base class wrapper makes it easier on code writing.. i.e. I don't need to implement interfaces. I just want to use my C++ code in C# Microsoft GOD!!!
EDIT:
I'm an idiot, I can access the private member...
This is just one answer... Still want to know why private setters arent' a thing
I just have to access my private member of my ConcreteClassWrapper and set the base class there. Then I can remove the set in the BaseClassWrapper property.
Did you try this :
property BaseClassWrapper^ BaseClass
{
BaseClassWrapper^ get() { return baseClass; }
private:
void set(BaseClassWrapper^ value) { baseClass= value; }
}
This is the way you write a private setter in a property. In the case of C++/CX, the property keyword is just a new keyword to allow C++/CX compiler to generate some C++ code, so the syntax for things like private, public, protected is the same.

groovy: variable scope in closures in the super class (MissingPropertyException)

I have the impression that closures run as the actual class being called (instead of the implementing super class) and thus break when some variables are not visible (e.g. private in the super class).
For example
package comp.ds.GenericTest2
import groovy.transform.CompileStatic
#CompileStatic
class ClosureScopeC {
private List<String> list = new ArrayList<String>()
private int accessThisPrivateVariable = 0;
void add(String a) {
list.add(a)
println("before ${accessThisPrivateVariable} ${this.class.name}")
// do something with a closure
list.each {String it ->
if (it == a) {
// accessThisPrivateVariable belongs to ClosureScopeC
accessThisPrivateVariable++
}
}
println("after ${accessThisPrivateVariable}")
}
}
// this works fine
a = new ClosureScopeC()
a.add("abc")
a.add("abc")
// child class
class ClosureScopeD extends ClosureScopeC {
void doSomething(String obj) {
this.add(obj)
}
}
b = new ClosureScopeD()
// THIS THROWS groovy.lang.MissingPropertyException: No such property: accessThisPrivateVariable for class: comp.ds.GenericTest2.ClosureScopeD
b.doSomething("abc")
The last line throws a MissingPropertyException: the child class calls the "add" method of the super class, which executes the "each" closure, which uses the "accessThisPrivateVariable".
I am new to groovy, so I think there must be an easy way to do this, because otherwise it seems that closures completely break the encapsulation of the private implementation done in the super class ... this seems to be a very common need (super class implementation referencing its own private variables)
I am using groovy 2.1.3
I found this to be a good reference describing how Groovy variable scopes work and applies to your situation: Closure in groovy cannot use private field when called from extending class
From the above link, I realized that since you have declared accessThisPrivateVariable as private, Groovy would not auto-generate a getter/setter for the variable. Remember, even in Java, private variables are not accessible directly by sub-classes.
Changing your code to explicitly add the getter/setters, solved the issue:
package com.test
import groovy.transform.CompileStatic
#CompileStatic
class ClosureScopeC {
private List<String> list = new ArrayList<String>()
private int accessThisPrivateVariable = 0;
int getAccessThisPrivateVariable() { accessThisPrivateVariable }
void setAccessThisPrivateVariable(int value ){this.accessThisPrivateVariable = value}
void add(String a) {
list.add(a)
println("before ${accessThisPrivateVariable} ${this.class.name}")
// do something with a closure
list.each {String it ->
if (it == a) {
// accessThisPrivateVariable belongs to ClosureScopeC
accessThisPrivateVariable++
}
}
println("after ${accessThisPrivateVariable}")
}
}
// this works fine
a = new ClosureScopeC()
a.add("abc")
a.add("abc")
// child class
class ClosureScopeD extends ClosureScopeC {
void doSomething(String obj) {
super.add(obj)
}
}
b = new ClosureScopeD()
b.doSomething("abc")
There is a simpler way, just make the access modifier (should rename the property really) to protected, so the sub-class has access to the property.. problem solved.
protected int accessThisProtectedVariable
To clarify on your statement of concern that Groovy possibly has broken encapsulation: rest assured it hasn't.
By declaring a field as private, Groovy is preserving encapsulation by intentionally suspending automatic generation of the public getter/setter. Once private, you are now responsible and in full control of how or if there is a way for sub-classes (protected) or all classes of objects (public) to gain access to the field by explicitly adding methods - if that makes sense.
Remember that by convention, Groovy ALWAYS calls a getter or setter when your codes references the field. So, a statement like:
def f = obj.someField
will actually invoke the obj.getSomeField() method.
Likewise:
obj.someField = 5
will invoke the obj.setSomeField(5) method.

non-static variable this cannot be referenced from a static context

I'm working with java me. I tried to switch to a displayable(form2) in Second.java from an okCommand in another displayble(form1) in First.java (see my previous question on that).
I got an error non-static method getForm2() cannot be referenced from a static context. I had to add the word static to form2 declaration and also at the getForm2 method in Second.java before it could work.
Problem now is that a backCommand in form2 can't switch back to form1 in First.java and it pops up the error non-static variable this cannot be referenced from a static context.
I paused and took some time to refresh myself on the language fundamentals on how the static keyword is used and I got to know that a static method is a class method and a non-static method is an instance method and that a non-static cannot call a static method unless an instance of the non-static method is created and also that a static method can't call a non-static method.
I'm really not understanding the implementation as I should, and I'd appreciate some clarification using my example above.
Here's the source below from Second.java the error is coming from form2.setCommandListener(this);
public static Form getForm2() {
if (form2 == null) {
form2 = new Form("form");
form2.addCommand(getBackCommand());
form2.setCommandListener(this);
}
return form2;
You have a static method, but are using this. But this doesn't exist. It would normally reference to an instance of the class, but you don't have one here.
If your method wasn't static and you instantiated an instance of this class then this would work.
e.g.
Second s = new Second();
Form f = s.getForm2(); // if this method wasn't static
Making that method static means little more than namespacing. There isn't an associated instance and no this.
There are couple options. First is to create a static instance of Second and use it in the getForm2:
//...
// static instance
private static Second instance = new Second(/* put constructor arguments here, if any */);
//...
public static Form getForm2() {
if (form2 == null) {
form2 = new Form("form");
form2.addCommand(getBackCommand());
form2.setCommandListener(instance); // --> replace "this" with "instance"
}
//...
From the issues you describe though, I would prefer another option - returning to design you had in previous question and use an instance of Second as an argument passed via constructor of First.
Your First.java would then have lines like:
//...
private final Second second; // instance needed for commandAction
//...
First(Second second) { // constructor with parameter
this.second = second; // save the parameter
//...
}
Then, commandAction method in First.java could use code like:
switchDisplayable(null, second.getSecondForm());
// instead of Second.getSecondForm()

Regarding String functionality

I was developing the below class..
public class Test1
{
public void method(Object o)
{
System.out.println("Object Verion");
}
public void method(String s)
{
System.out.println("String Version");
}
public static void main(String args[])
{
Test1 question = new Test1();
//question.method(question);
question.method(null);
}
}
Now upon executing it invokes string version as output So please advise here string is treated as null and what should we pass to invoke the object version.Thanks in advance
All other things being equal, the most-specific method will be called. From the JLS:
15.12.2.5. Choosing the Most Specific Method
If more than one member method is both accessible and applicable to a
method invocation, it is necessary to choose one to provide the
descriptor for the run-time method dispatch. The Java programming
language uses the rule that the most specific method is chosen.
The informal intuition is that one method is more specific than
another if any invocation handled by the first method could be passed
on to the other one without a compile-time type error.
question.method(null) could mean either the String or Object overload, but since String is more specific (narrower) than Object, the String overload is the method that is called.

Can i make a linq expression optional parameter in c# 4.0?

I have the following code.
public void GetMessages(Expression<Func<IMessageQueryable, bool>> messageSpecification, string folder = "INBOX")
{
// Implementation stripped
}
How can i provide default value for messageSpecification?. Specification says the value must be a compile time constant. Is this possible?.
EDIT: Not lookig for specifying it as Expression<Func<IMessageQueryable, bool>> messageSpecification = null
You can OverLoad it. What would your default value be?
Why bother? Create an overload for the same method without messageSpecification parameter and define it's default value yourself inside the overloaded method and pass it to your original method. Default parameters are actually never meant to be used like that anyway.
public void GetMessages(string folder = "INBOX")
{
this.GetMessages(DEFAULT_VALUE, folder);
}

Resources