473,408 Members | 2,839 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,408 software developers and data experts.

Generics and delegates

I'm trying to "genericize" the following class. At the moment I have
derived classes for each different type of event handler / event
arguments, and I wanted to have a single, generic, catch-all class for
wrapping an event subscription in a "weak" event handler.

Unfortunately, I've been bitten by the restriction that one can't do
this:

public class Blah<T: WeakReference where T : Delegate

because the compiler complains that "System.Delegate" isn't a valid
constraint. Can anyone give me a pointer or two on how to restructure
this to create a generic weak reference delegate? (The code has been
stripped down to remove some comments and error checking, and no, it
doesn't compile as written.)

/// <summary>
/// Used to subscribe to <em>static</emevents
/// when the subscriber wants to subscribe via a weak reference
rather than a strong
/// reference.
/// </summary>
/// <remarks>Subscribing via a weak reference allows event
subscribers to be
/// garbage collected without having to unsubscribe to the event,
but it also
/// comes with a host of concurrency considerations, not the least
of which
/// is that the event handler method on the subscriber could be
called and be
/// executing while the object is being garbage collected!
/// <para>Subscribing via weak references is usually done when
subscribing to
/// static events, since the event supplier will never be garbage
collected,
/// and so anything to which it holds strong references (regular
event
/// subscriptions) will never be garbage collected.</para>
/// </remarks>
public abstract class WeakEventReference<A, H: WeakReference
{
private EventInfo _provider;
private MethodInfo _subscriberMethod;

protected WeakEventReference(object subscriber, MethodInfo
subscriberMethod, EventInfo provider) : base(subscriber)
{
this._subscriberMethod = subscriberMethod;
ParameterInfo[] subscriberMethodParameters =
subscriberMethod.GetParameters();
this._provider = provider;
}

protected WeakEventReference(object subscriber, Type
subscriberType, string subscriberMethod, Type providerType, string
providerEvent) : base(subscriber)
{
this._subscriberMethod =
subscriberType.GetMethod(subscriberMethod, BindingFlags.Instance |
BindingFlags.NonPublic | BindingFlags.Public);
ParameterInfo[] subscriberMethodParameters =
this._subscriberMethod.GetParameters();
if (providerType == null)
{
this._provider = null;
}
else
{
this._provider = providerType.GetEvent(providerEvent);
}
}

/// <summary>
/// Gets the event provider for the event to which the weak
/// reference delegate has subscribed.
/// </summary>
/// <value>Information about the event to which this weak
/// reference is subscribing.</value>
protected EventInfo Provider
{
get { return this._provider; }
}

/// <summary>
/// Gets the method information for the method to call on the
/// event subscriber.
/// </summary>
/// <value>Information about the method that this weak
reference
/// is to call each time the event occurs.</value>
protected MethodInfo SubscriberMethod
{
get { return this._subscriberMethod; }
}

/// <summary>
/// The event handler that will really be subscribed to the
event.
/// </summary>
/// <param name="sender">The object that raised the event.</
param>
/// <param name="args">Arguments giving more information about
the event.</param>
public void Handler(object sender, A args)
{
object sub = this.Target;
if (sub != null)
{
this.SubscriberMethod.Invoke(sub, new object[]
{ sender, args });
}
else if (this.Provider != null)
{
// Error here: H is not a System.Delegate
this.Provider.RemoveEventHandler(null, this.Delegate);
}
}

/// <summary>
/// The delegate to add to the event dispatch chain.
/// </summary>
/// <value>The event handler delegate for this object's
/// <see cref="Handler"/method.</value>
public H Delegate
{
// Error here: H is not "newable"
get { return new H(this.Handler); }
}
}

Jul 19 '07 #1
1 1850
Bruce,

While it is not an optimal solution, you could perform a run-time check,
where in the static constructor for the type you check T to make sure that
it derives from Delegate. It's not optimal, but it's the only choice you
have with the current constraint system.

If the delegates that you are going to handle always follow the standard
pattern (first parameter is of type Object, second parameter of a type
deriving from EventArgs), then you could make the constraint on EventArgs,
and assume that the parameter list will adhere to the standard event
pattern.
--
- Nicholas Paldino [.NET/C# MVP]
- mv*@spam.guard.caspershouse.com

"Bruce Wood" <br*******@canada.comwrote in message
news:11*********************@e16g2000pri.googlegro ups.com...
I'm trying to "genericize" the following class. At the moment I have
derived classes for each different type of event handler / event
arguments, and I wanted to have a single, generic, catch-all class for
wrapping an event subscription in a "weak" event handler.

Unfortunately, I've been bitten by the restriction that one can't do
this:

public class Blah<T: WeakReference where T : Delegate

because the compiler complains that "System.Delegate" isn't a valid
constraint. Can anyone give me a pointer or two on how to restructure
this to create a generic weak reference delegate? (The code has been
stripped down to remove some comments and error checking, and no, it
doesn't compile as written.)

/// <summary>
/// Used to subscribe to <em>static</emevents
/// when the subscriber wants to subscribe via a weak reference
rather than a strong
/// reference.
/// </summary>
/// <remarks>Subscribing via a weak reference allows event
subscribers to be
/// garbage collected without having to unsubscribe to the event,
but it also
/// comes with a host of concurrency considerations, not the least
of which
/// is that the event handler method on the subscriber could be
called and be
/// executing while the object is being garbage collected!
/// <para>Subscribing via weak references is usually done when
subscribing to
/// static events, since the event supplier will never be garbage
collected,
/// and so anything to which it holds strong references (regular
event
/// subscriptions) will never be garbage collected.</para>
/// </remarks>
public abstract class WeakEventReference<A, H: WeakReference
{
private EventInfo _provider;
private MethodInfo _subscriberMethod;

protected WeakEventReference(object subscriber, MethodInfo
subscriberMethod, EventInfo provider) : base(subscriber)
{
this._subscriberMethod = subscriberMethod;
ParameterInfo[] subscriberMethodParameters =
subscriberMethod.GetParameters();
this._provider = provider;
}

protected WeakEventReference(object subscriber, Type
subscriberType, string subscriberMethod, Type providerType, string
providerEvent) : base(subscriber)
{
this._subscriberMethod =
subscriberType.GetMethod(subscriberMethod, BindingFlags.Instance |
BindingFlags.NonPublic | BindingFlags.Public);
ParameterInfo[] subscriberMethodParameters =
this._subscriberMethod.GetParameters();
if (providerType == null)
{
this._provider = null;
}
else
{
this._provider = providerType.GetEvent(providerEvent);
}
}

/// <summary>
/// Gets the event provider for the event to which the weak
/// reference delegate has subscribed.
/// </summary>
/// <value>Information about the event to which this weak
/// reference is subscribing.</value>
protected EventInfo Provider
{
get { return this._provider; }
}

/// <summary>
/// Gets the method information for the method to call on the
/// event subscriber.
/// </summary>
/// <value>Information about the method that this weak
reference
/// is to call each time the event occurs.</value>
protected MethodInfo SubscriberMethod
{
get { return this._subscriberMethod; }
}

/// <summary>
/// The event handler that will really be subscribed to the
event.
/// </summary>
/// <param name="sender">The object that raised the event.</
param>
/// <param name="args">Arguments giving more information about
the event.</param>
public void Handler(object sender, A args)
{
object sub = this.Target;
if (sub != null)
{
this.SubscriberMethod.Invoke(sub, new object[]
{ sender, args });
}
else if (this.Provider != null)
{
// Error here: H is not a System.Delegate
this.Provider.RemoveEventHandler(null, this.Delegate);
}
}

/// <summary>
/// The delegate to add to the event dispatch chain.
/// </summary>
/// <value>The event handler delegate for this object's
/// <see cref="Handler"/method.</value>
public H Delegate
{
// Error here: H is not "newable"
get { return new H(this.Handler); }
}
}
Jul 19 '07 #2

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

Similar topics

17
by: Andreas Huber | last post by:
What follows is a discussion of my experience with .NET generics & the ..NET framework (as implemented in the Visual Studio 2005 Beta 1), which leads to questions as to why certain things are the...
16
by: bigtexan | last post by:
I would like to do the following and cannot figure it out. public class A<T> { public delegate T GetValueDelegate(A<T> var); public GetValueDelegate GetValue = new GetValueDelegate(B.GetValue);...
12
by: Michael S | last post by:
Why do people spend so much time writing complex generic types? for fun? to learn? for use? I think of generics like I do about operator overloading. Great to have as a language-feature, as...
9
by: sloan | last post by:
I'm not the sharpest knife in the drawer, but not a dummy either. I'm looking for a good book which goes over Generics in great detail. and to have as a reference book on my shelf. Personal...
4
by: Cedric Rogers | last post by:
I wasn't sure if I could do this. I believe I am stretching the capability of what generics can do for me but here goes. I have a generic delegate defined as public delegate bool...
14
by: dave.dolan | last post by:
Basically I'd like to implement the composite design pattern with leaves that are either of reference or value types, but even using generics I can't seem to avoid boxing (using ArrayList or...
4
by: Bill Woodruff | last post by:
< note : this message was sparked in part by comments by David Browne on a previous thread : "inserting an anonymous method as a value in a generic dictionary ?" : David had shown the use of...
9
by: James Crosswell | last post by:
I'm not sure if I'm going about this the right way - it may be that Generics might be able to help me out here... but here goes: I have three classes as follows class BaseEdit class WidgetEdit:...
3
by: rbjorkquist | last post by:
I am looking for some help figuring out the best way to refactor these two examples. I was thinking of using delegates and/or generics; but have little experience with either. Any sample code...
8
by: Tony Johansson | last post by:
Hello! I have read that in practice, casting proved to be several times faster than using a generic. So the main reason to use generics is not that the performance is better because that's...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
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
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
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
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...
0
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new...

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.