473,387 Members | 1,495 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,387 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 1847
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
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
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...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
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,...

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.