473,388 Members | 1,346 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,388 software developers and data experts.

Problem using Reflection to Assign Generic Delegates

Hi folks

I have a Generic Value Type and I want to detect when the internal value
changes.

///////////////////////////////
public delegate void ValueTypeValidationHandler<T>(T oldValue, T newValue);

public struct TestType<T>
{
private T value;

public event ValueTypeValidationHandler<T> valueChanged;

public ValueType(T value)
{
this.value = value;
valueChanged = null;
}

public T Value
{
get { return value; }
set
{
if(valueChanged != null)
valueChanged(this.value, value);

this.value = value;
}
}
}
//////////////////////

I want to be able to add TestType<> fields to a containing class and have
the containing class assign a delegate to each of the TestType<> fields
without naming them specifically, in the constructor of the containing
class.

So far I have got this far but I want to know how to attach the delegates to
the events.

/////////////////////////
public ContainingType()
{
FieldInfo[] fia = GetType().GetFields(BindingFlags.Instance |
BindingFlags.NonPublic);

foreach(FieldInfo fi in fia)
{
Type ft = fi.FieldType;

object fObj = fi.GetValue(this);

// the next line doesn't compile; how do I pass the type of each field into
the
generic parameters ?

((TestType<ft>) fObj).valueChanged += new
ValueTypeValidationHandler<ft>(HandleValueChanged< ft>);
}
////////////////////////////

TIA

Joanna

--
Joanna Carter
Consultant Software Engineer
Nov 16 '05 #1
6 2272
Hi!

How have you declared your HandleValueChanged method?
"Joanna Carter (TeamB)" wrote:
Hi folks

I have a Generic Value Type and I want to detect when the internal value
changes.

///////////////////////////////
public delegate void ValueTypeValidationHandler<T>(T oldValue, T newValue);

public struct TestType<T>
{
private T value;

public event ValueTypeValidationHandler<T> valueChanged;

public ValueType(T value)
{
this.value = value;
valueChanged = null;
}

public T Value
{
get { return value; }
set
{
if(valueChanged != null)
valueChanged(this.value, value);

this.value = value;
}
}
}
//////////////////////

I want to be able to add TestType<> fields to a containing class and have
the containing class assign a delegate to each of the TestType<> fields
without naming them specifically, in the constructor of the containing
class.

So far I have got this far but I want to know how to attach the delegates to
the events.

/////////////////////////
public ContainingType()
{
FieldInfo[] fia = GetType().GetFields(BindingFlags.Instance |
BindingFlags.NonPublic);

foreach(FieldInfo fi in fia)
{
Type ft = fi.FieldType;

object fObj = fi.GetValue(this);

// the next line doesn't compile; how do I pass the type of each field into
the
generic parameters ?

((TestType<ft>) fObj).valueChanged += new
ValueTypeValidationHandler<ft>(HandleValueChanged< ft>);
}
////////////////////////////

TIA

Joanna

--
Joanna Carter
Consultant Software Engineer

Nov 16 '05 #2
"robkit" <ro****@discussions.microsoft.com> a écrit dans le message de news:
9E**********************************@microsoft.com...
Hi!

How have you declared your HandleValueChanged method?


Thanks for replying...

private void HandleValueChanged<T>(T oldValue, T newValue) {...}

Have I made it clear enough what I am trying to do ? Is this something to do
with 'method groups' ?

Joanna

--
Joanna Carter
Consultant Software Engineer
Nov 16 '05 #3
Joanna,
the containing class assign a delegate to each of the TestType<> fields
without naming them specifically


How important is this? It would sure make the code cleaner if you
could just name the fields rather than using Reflection.

If you start using Reflection you pretty much have to do it all the
way, and it gets kind of ugly. I think something like this shuld do it
Debug.Assert(ft.HasGenericArguments && ft.GetGenericArguments().Length
== 1 );
Type typeArgument = ft.GetGenericArguments()[0];

Type handlerType =
typeof(ValueTypeValidationHandler<object>).GetGene ricTypeDefinition().BindGenericParameters(
new Type[] {typeArgument} );
Delegate handler = Delegate.CreateDelegate( handlerType,
typeof(ContainingType).GetMethod("HandleValueChang ed",
BindingFlags.Instance|BindingFlags.NonPublic).Bind GenericParameters(
typeArguments ) );
ft.GetEvent( "valueChanged" ).AddEventHandler( fObj, handler );
But this will only work as expected if you change TestType to a class,
because otherwise you just end up modifying a boxed copy of the field.

Mattias

--
Mattias Sjögren [MVP] mattias @ mvps.org
http://www.msjogren.net/dotnet/ | http://www.dotnetinterop.com
Please reply only to the newsgroup.
Nov 16 '05 #4
"Mattias Sjögren" <ma********************@mvps.org> a écrit dans le message
de news: #4**************@tk2msftngp13.phx.gbl...
How important is this? It would sure make the code cleaner if you
could just name the fields rather than using Reflection.
The idea is to have a method called from the base class constructor that
takes care of linking up a delegate in the containing class to the
ValueChanged events in my ValueType fields. Then all that has to be done in
derived classes is to add fields appropriate to the business class required.

In a previous version of this framework I wrote in Delphi, I simply added
the ValueTypes to a HashTable and accessed them by named index; I was just
experimenting with generics and trying to cut down on coding :-)

I could always revert to the standard Observer pattern, but I am trying to
exploit the built-in broadcasting mechanism already provided by multicast
delegates.
If you start using Reflection you pretty much have to do it all the
way, and it gets kind of ugly. I think something like this shuld do it <snip>

I will try this but I think your next comment about boxing may well be the
problem.
But this will only work as expected if you change TestType to a class,
because otherwise you just end up modifying a boxed copy of the field.


Is there no way to unbox the TestType from the object? I thought casting it
to the original type would extract it, but that doesn't seem to work.

Regards

Joanna

--
Joanna Carter
Consultant Software Engineer
Nov 16 '05 #5
Joanna,
The idea is to have a method called from the base class constructor that
takes care of linking up a delegate in the containing class to the
ValueChanged events in my ValueType fields.
Sounds like a potentially dangerous design. By the time the base class
constructor runs, the fields in the derived class may not have been
initialized yet.

Is there no way to unbox the TestType from the object?


Sure, but to unbox you need compile time knowledge of the type you
want to cast too, i.e. if it's a TestType<Foo> or a TestType<Bar>.
Which brings be back to the point that using Reflection here may just
be problematic.

Mattias

--
Mattias Sjögren [MVP] mattias @ mvps.org
http://www.msjogren.net/dotnet/ | http://www.dotnetinterop.com
Please reply only to the newsgroup.
Nov 16 '05 #6
"Mattias Sjögren" <ma********************@mvps.org> a écrit dans le message
de news: uF**************@TK2MSFTNGP10.phx.gbl...
Sounds like a potentially dangerous design. By the time the base class
constructor runs, the fields in the derived class may not have been
initialized yet.
You are, of course, right; I am used to being able to call code before the
base constructor in Delphi.
Sure, but to unbox you need compile time knowledge of the type you
want to cast too, i.e. if it's a TestType<Foo> or a TestType<Bar>.
I had read about using unbound generic types and was hoping that that might
have provided an answer :-(
Which brings be back to the point that using Reflection here may just
be problematic.


OK, I'm still trying to adjust from Delphi's RTTI to reflection and finding
out what it can and cannot do.

Joanna

--
Joanna Carter (TeamB)

Consultant Software Engineer
Nov 16 '05 #7

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

1
by: andrew queisser | last post by:
I've been trying to dynamically create a class DevT that's derived from a generic base GenBase<T>. It doesn't seem to work. I'm attaching a code sample below that illustrates the problem. ...
8
by: Rob R. Ainscough | last post by:
I use a generic Processing form (modal) where I pass it an object and method name and parameters if needed and then use CallbyName to execute the passed in method. What this does for me is lock...
10
by: =?Utf-8?B?QnJpYW4=?= | last post by:
What is the easiest way to convert primitives to a byte array? I tried the BinaryFormatter serialization but it serializes objects so when I serialized an and int it took 54 bytes instead of 4. I...
9
by: raylopez99 | last post by:
Hello all— I’m trying to get the below to work and cannot get the format right. It’s from this example: http://msdn.microsoft.com/en-us/library/8627sbea(VS.71).aspx What it is: I’m trying...
0
by: taylorcarr | last post by:
A Canon printer is a smart device known for being advanced, efficient, and reliable. It is designed for home, office, and hybrid workspace use and can also be used for a variety of purposes. However,...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.