.NETGURU
HELP: Late Construction via Reflection & instance variable initializers
Messages   Related Types
This message was discovered on microsoft.public.dotnet.framework.
Responses highlighted in red are from those people who are likely to be able to contribute good, authoratitive information to this discussion. They include Microsoft employees, MVP's and others who IMHO contribute well to these kinds of discussions.
Post a new message to this list...

Robert Hooker
Hi All,

I not sure if I am doing something wrong, or if this is a bug in the
framework somewhere - but I'm having trouble with instance variable
initialization which is done before any of the ctors are called.

Very simple code follows! Any help much appreciated!

Given this class:

public class Wibble
{
public int var1 /*=0*/; //Intentionally left at 'default'
public int var2 =0;

public Wibble(){}
}

Then, when I do this:

Wibble w = new Wibble();

//Correct: var1=0 and var2=0
System.Console.WriteLine("Step1 : var1={0} var2={1}",w.var1,w.var2);

w.var1 = 66; w.var2 = 77;
//Correct: var1=66 and var2=77
System.Console.WriteLine("Step2 : var1={0} var2={1}",w.var1,w.var2);

So far so good. However, if I now get the default ctor via reflection, and
r-invoke it, one of my instance variables fails to re-initialize - like so:

//Obtain the default ctor via reflection
ConstructorInfo ci =
typeof(Wibble).GetConstructor(BindingFlags.Instance|BindingFlags.Public|
BindingFlags.NonPublic, null, CallingConventions.Any, Type.EmptyTypes,
null);
//Re-Invoke the default ctor via reflection
ci.Invoke(w,null);

//** INCORRECT ** ?? var1=66 and var2=0
System.Console.WriteLine("Step3 : var1={0} var2={1}",w.var1,w.var2);

Can anyone see what I am doing wrong? Am I misunderstanding the behaviour of
ctors etc?
Rob.

PS: Actual .cs file is attached

Reply to this message...
 
    
Richard Blewett
Robert,

this is expected behavior

look at the IL for the generated ctor

IL_0000: ldarg.0
IL_0001: ldc.i4.0
IL_0002: stfld int32 Wibble::var2 // Look at this line
IL_0007: ldarg.0
IL_0008: call instance void [mscorlib]System.Object::.ctor()
IL_000d: ret

The field initializer gets translated into a stfld in the generated
constructor

Now your

Wibble w - new Wibble();

will generate an IL op code of initobj. initobj will zero the memory of the
object. So in effect your field initializer is superfluous as it only
repeats the default CLR based initialization.

The main question I guess is why on earth are you re-running the
constructor? are you trying to re-initialize the object back to its original
state? If this is the case you would be far better off
just creating a new object as object creation in .NET is incredibly cheap
(in general). if you have an edge case where your objewct is very expensive
to create then I would advise you to ann an Initialize method to Wibble and
let the client call that rather than try to re-execute the ctor.

Regards

Richard Blewett - DevelopMentor
http://staff.develop.com/richardb/weblog

"Robert Hooker" <Click here to reveal e-mail address> wrote in message
news:Click here to reveal e-mail address...
[Original message clipped]

Reply to this message...
 
    
Robert Hooker
[Original message clipped]


I have a case where an instance of 'wibble' is referenced by 'n' other
objects. I need to reinitialize the wibble instance back to its original
state, but I don't own wibble sourcecode, nor do I have any control over it
(so I can't add a 'ReInit' style method).

If those 'n' other objects reference a wibble instance and I actually create
a brand "new Wibble()" - then the references will different and I'll be in
fixup\translate hell - a situation I'm trying to avoid! :-) [Especially
since I don't own the 'n' other object either, so I can't add methods to
'fixup' the reference]

Is there a better way to achieve what I'm trying to do?

"Richard Blewett" <Click here to reveal e-mail address> wrote in message
news:Click here to reveal e-mail address...
[Original message clipped]

Reply to this message...
 
    
Robert Jordan
Hi Robert,

[Original message clipped]

How about this:

- create a new Wibble instance
- reflect on the new instance *andÜ on the instance you want
to reset and set the fields to the values of the
new instance.

bye
Rob

[Original message clipped]

Reply to this message...
 
    
Robert Jordan
[Original message clipped]

pseudo code:

static void ResetWibble(Wibble old) {
Wibble w = new Wibble();

FieldInfo[] newFields = w.GetType.GetFields(...);
FieldInfo[] oldFields = old.GetType.GetFields(...);

for (int i = 0; i < newFields.Length; i++) {
newFields[i].SetValue(old, oldFields[i].GetValue(w));
}

}

bye
Rob
Reply to this message...
 
    
Richard Blewett [DevelopMentor] (VIP)
The only problem with this approach (though at the moment I don't have a massive alternative without resorting to IL) is that :

1) you need to know how the initialization of Wibble actually works. It probably isn't as simple as zeroing out the fields

2) You need to be running with a high level of trust to be able to be able to reflect on private members – CAS may be your undoing.

To be honest, unless you are going to resort to IL (pass in the objref to a method and call initobj and then the ctor in that method) then I don't think you have a foolproof way of doing this) – and without testing I'm not sure that this approach would be verifiable (although I can't think of why it wouldn't be) and if it isn't you may still fall foul of CAS.

Regards

Richard Blewett – DevelopMentor

http://staff.develop.com/richardb/weblog

nntp://news.microsoft.com/microsoft.public.dotnet.framework.clr/<chvdru$cc6$07$Click here to reveal e-mail address>

[Original message clipped]

pseudo code:

static void ResetWibble(Wibble old) {
Wibble w = new Wibble();

FieldInfo[] newFields = w.GetType.GetFields(...);
FieldInfo[] oldFields = old.GetType.GetFields(...);

for (int i = 0; i < newFields.Length; i++) {
newFields[i].SetValue(old, oldFields[i].GetValue(w));
}

}

bye
Rob

---
Incoming mail is certified Virus Free.
Checked by AVG anti-virus system (http://www.grisoft.com).
Version: 6.0.759 / Virus Database: 508 - Release Date: 09/09/2004

[microsoft.public.dotnet.framework.clr]

Reply to this message...
 
    
Robert Jordan
Hi Richard,

[Original message clipped]

I forgot to mention, that Robert's trick (the constructor
invocation via reflection) is still required, since
the constructor may contain some logic.

[Original message clipped]

It's saturday ;-)

bye
Rob

[Original message clipped]

Reply to this message...
 
    
Richard Blewett [DevelopMentor] (VIP)
Its OK Robert,

In fact you're approach is better if we assume the IL approach would cause a CAS issue. You can zero then run the ctor and not have to handcraft a module or assembly in raw IL J

Regards

Richard Blewett – DevelopMentor

http://staff.develop.com/richardb/weblog

nntp://news.microsoft.com/microsoft.public.dotnet.framework.clr/<chvr7c$8o1$04$Click here to reveal e-mail address>

Hi Richard,

[Original message clipped]

I forgot to mention, that Robert's trick (the constructor
invocation via reflection) is still required, since
the constructor may contain some logic.

[Original message clipped]

It's saturday ;-)

bye
Rob

[Original message clipped]

---
Incoming mail is certified Virus Free.
Checked by AVG anti-virus system (http://www.grisoft.com).
Version: 6.0.759 / Virus Database: 508 - Release Date: 09/09/2004

[microsoft.public.dotnet.framework.clr]

Reply to this message...
 
    
Robert Hooker
Richard and Robert,

Thanks for your replies (on a saturday!).

The following seems to work - though I'm vaguely uneasy about it. Its a
combo of both of your replies (but without resorting to IL)

Wibble w = new Wibble()
// stuff occurs to alter the state of wibble
;

//This sets everything to 'zero' on a new Wibblw instance - but doesn't call
any ctors (so I assume its fairly cheap)
object o = FormatterServices.GetUninitializedObject(typeof(wibble);

//Copy the 'zero's' across to my Wibble instance
foreach (FieldInfo fi in WibblesFields)
{
fo.SetValue(w, fi.GetValue(o));
}

//Then invoke the ctor of wibble - this sets up all values which are 'zero'
ci = GetConstructor();
co.Invoke(w,null)

My uneasiness comes from the fact thatf or most fields I'll be setting them
to zero, then the ctor will assign the real value - kind of wasteful...

"Richard Blewett [DevelopMentor]" <Click here to reveal e-mail address> wrote in message
news:Click here to reveal e-mail address...
> The only problem with this approach (though at the moment I don't have a
massive alternative without resorting to IL) is that :
[Original message clipped]

think you have a foolproof way of doing this) – and without testing
I'm not sure that this approach would be verifiable (although I can't think
of why it wouldn't be) and if it isn't you may still fall foul of CAS.
[Original message clipped]

Reply to this message...
 
    
Robert Jordan
Robert Hooker wrote:

[Original message clipped]

cool! ;-)

bye
Rob

[Original message clipped]

Reply to this message...
 
 
System.Console
System.Object
System.Reflection.BindingFlags
System.Reflection.CallingConventions
System.Reflection.ConstructorInfo
System.Reflection.FieldInfo
System.Runtime.Serialization.FormatterServices
System.Type




ExamGuru IT Solutions - .Net Guru is owned and operated by ExamGuru, Inc., the man behind .Net Guru. If you're in the market for bespoke software or software consultancy, why not get him and his highly trained team to help? - www.examguru.net/ITCertification
Ad


Need Dot Net Interview Questions?
Ask ExamGuru, Inc. for advice and help on Passing .Net Interviews
.Net Projects
Best-of-breed application framework for .NET projects, developed by ExamGuru, Inc. and ExamGuru IT
Free .net Help
Commission ExamGuru, Inc. and his team for your next bespoke software project
FogBUGZ
The only bug tracking system carefully crafted with one goal in mind: helping teams create great software.
Awesome Tools
If you don't know about these, you're missing out... IT Certification Questions
IT Interview Questions
Free Oracle 10g Training
MCSE Boortcamp
Cisco Study Guides
Cheap Study Guides
Exact Questions
Dot Net Interview Questions
Oracle OCP
Cheap Travel
Designer Perfumes - Wholesale Prices
Free Programming Tutorials
 
ExamGuru IT Solutions - .Net Guru is owned and operated by ExamGuru, Inc., the man behind .Net Guru. If you're in the market for bespoke software or software consultancy, why not get him and his highly trained team to help? - www.examguru.net/ITCertification
 Copyright © ExamGuru, Inc. 2001-2006
Contact Us - Terms of Use - Privacy Policy - www.dot-net-guru.com - www.examguru.net - www.oraclesource.net - www.itinterviews.net - www.examguru.net/ITCertification