"Override" static method via DynamicMethod

N

none

I'd like to create a new static property in a class "hiding" the
property present in a base class. Since this needs to happen at runtime
I tried doing this via DynamicMethod. But obviously the created methods
are not "registered" and only available through the DynamicMethod class.
So a method lookup finds the origin property.

A little test:

public class DerivedClass : BaseClass
{
public static DynamicMethod CustomMethod;
}

public class BaseClass
{
public static int Something
{
get
{
return 5;
}
}

public static void Main(string[] args)
{
DerivedClass.CustomMethod = new
System.Reflection.Emit.DynamicMethod("get_Something",
MethodAttributes.NewSlot | MethodAttributes.Static |
MethodAttributes.Public, CallingConventions.Standard, typeof(int), null,
typeof(DerivedClass), false);
ILGenerator generator = DerivedClass.CustomMethod.GetILGenerator();

generator.Emit(OpCodes.Ldc_I4, 3);
generator.Emit(OpCodes.Ret);

Console.WriteLine("BaseClass: " + Something.ToString() + "
DerivedClass: " + DerivedClass.Something.ToString());
}
}

Currently gives BaseClass: 5 DerivedClass: 5.
I'd like it to give me BaseClass: 5 DerivedClass: 3.
(How) can this be achived?

Regards
LCID Fire
 
J

Jon Skeet [C# MVP]

I'd like to create a new static property in a class "hiding" the
property present in a base class. Since this needs to happen at runtime
I tried doing this via DynamicMethod. But obviously the created methods
are not "registered" and only available through the DynamicMethod class.
So a method lookup finds the origin property.

You've got bigger problems than that - if you decompile the IL, you'll
find that because DerivedClass doesn't have a Something property at
compile-time, the call to DerivedClass.Something is actually compiled
directly into a call to BaseClass.Something.
 
N

none

Jon said:
You've got bigger problems than that - if you decompile the IL, you'll
find that because DerivedClass doesn't have a Something property at
compile-time, the call to DerivedClass.Something is actually compiled
directly into a call to BaseClass.Something.
Ok, aside from the question whether statics should derive from base
classes one could restructure the code to:

public class DerivedClass : BaseClass
{
public static DynamicMethod _dc;
}

public class BaseClass
{
public virtual int get_Something()
{
return 5;
}

public static void Main(string[] args)
{
DerivedClass._dc = new
System.Reflection.Emit.DynamicMethod("get_Something",
MethodAttributes.Public, CallingConventions.Standard, typeof(int), null,
typeof(DerivedClass), false);
ILGenerator generator = DerivedClass._dc.GetILGenerator();

generator.Emit(OpCodes.Ldc_I4, 3);
generator.Emit(OpCodes.Ret);

Console.WriteLine("BaseClass: " + new
BaseClass().get_Something().ToString() + " DerivedClass: " + new
DerivedClass().get_Something().ToString());
}
}

Nevertheless it doesn't work. What am I doing wrong?
 
J

Joanna Carter [TeamB]

"none" <""lcid-fire\"@(none)"> a écrit dans le message de (e-mail address removed)...

| Ok, aside from the question whether statics should derive from base
| classes one could restructure the code to:

Static methods belong to the class in which they are declared, you have to
declare another method of the same type in the derived class in order to get
different behaviour :

public class BaseClass
{
public static int get_Something()
{
return 5;
}
}

public class DerivedClass : BaseClass
{
public static int get_Something()
{
return 3;
}
}

And you really don't need LCG or dynamic methods to call the appropriate
static method :

public int GetInt<T>() where T : BaseClass
{
Type type = typeof(T);

MethodInfo mi = type.GetMethod("get_Something", BindingFlags.Public |
BindingFlags.Static);

return (int) mi.Invoke(null, null);
}

.... and this method gets called like this :

{
// either
int i = GetInt<BaseClass>();

// or

int i = GetInt<DerivedClass>();
}

Joanna
 
N

none

Joanna said:
"none" <""lcid-fire\"@(none)"> a écrit dans le message de (e-mail address removed)...

| Ok, aside from the question whether statics should derive from base
| classes one could restructure the code to:

Static methods belong to the class in which they are declared, you have to
declare another method of the same type in the derived class in order to get
different behaviour :
Ok, but what I don't see is why the clr cannot search for the "highest"
implementation of a static method. You have the derivance, even if you
don't have a class instance yet.
And you really don't need LCG or dynamic methods to call the appropriate
static method :
That's my problem. I definately don't know at compile time, which value
I want to override. This is all taken out of xml files.
So I read in the xml files and want to change some initial values.

Would this be possible if I create a temporarily copy of each type and
change this via the TypeBuilder (something similar to the page handling
in ASP.NET)?

public int GetInt<T>() where T : BaseClass
{
Type type = typeof(T);

MethodInfo mi = type.GetMethod("get_Something", BindingFlags.Public |
BindingFlags.Static);

return (int) mi.Invoke(null, null);
}
Thanks for the hint. Doing a typeof(T) didn't cross my mind so far. I
could use something on some other code.
 
J

Joanna Carter [TeamB]

"none" <""lcid-fire\"@(none)"> a écrit dans le message de (e-mail address removed)...

| Ok, but what I don't see is why the clr cannot search for the "highest"
| implementation of a static method. You have the derivance, even if you
| don't have a class instance yet.

I think what you are after is a feature like Delphi class references, which
facilitate virtual constructors and virtual static methods. This is
something that can be emulated by designing a "metaclass".

A metaclass is usually designed as nested class within the base class, that
can only be instantiated through a static method of the base class, but that
possesses virtual instance methods that call the correct constructor or
static method on a given derived type using similar techniques to the method
I gave as an example.

public class ClassReference<T>
{
public T Create<U>() where U : T
{
// code to call default constructor on U
}

protected T Create<U>(object[] ctorArgs) where U : T
{
// code to call parameterised constructor on U
}
}

public class Base
{
public class ClassReference : ClassReference<Base>
{
public Base Create<U>() where U : Base
{
return base.Create<U>();
}

public Base Create<U>(int value) where U : Base
{
return base.Create<U>(new object[] { value });
}

// additional "virtual static" method
public int GetValue<U>() where U : T
{
Type type = typeof(U);

MethodInfo mi = type.GetMethod("GetValue", BindingFlags.Public |
BindingFlags.Static);

return (int) mi.Invoke(null, null);
}
}

public static ClassReference ClassRef
{
get { return new ClassReference(); }
}

private int value;

public Base() : this(0) { }

public Base(int value)
{
this.value = value;
}

public static int GetValue()
{
return 5;
}
}

public class Derived : Base
{
public Derived() : base() { }

public Derived(int value) : base(value) { }

public static new int GetValue()
{
return 3;
}
}

Used like this :

{
Base.ClassReference cr = Base.ClassRef;

Base b = cr.Create<Derived>();

int i = cr.GetValue<Base>();

// or

int i = cr.GetValue<Derived>();
}

| That's my problem. I definately don't know at compile time, which value
| I want to override. This is all taken out of xml files.
| So I read in the xml files and want to change some initial values.

Then modify the metaclass idea to take a Type parameter instead of a generic
parameter, and use Type GetType(string) to get the type to pass in.

{
Base.ClassReference cr = Base.ClassRef;

Type derivedType = Type.GetType("Derived");

Base b = cr.Create(derivedType);

int i = cr.GetValue(typeof(Base));

// or

int i = cr.GetValue(derivedType);
}

Joanna
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top