471,337 Members | 1,256 Online
Bytes | Software Development & Data Engineering Community
Post +

Home Posts Topics Members FAQ

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

Can this be done via .net generics? How?

Can this be done via .net generics? How? The % signs below are just to show
how I want to do it, I realise they're not valid syntax.

public abstract class BaseSelectionRequirement {
...
protected Type mControlType;
protected string mFieldName;
protected Type mFieldType;
protected UserControl mControl;
...

public %mFieldType% Value {
get {
return ( ( %mControlType% ) mControl ).%mFieldName%;
}
set {
( ( %mControlType% ) mControl ).%mFieldName% = value;
}
}
}

So, say my descended class was:

public class HatSelectionRequirement : BaseSelectionRequirement {
public HatSelectionRequirement( ) {
mControlType = HatUserControl;
mFieldType = typeof( Int32 );
mFieldName = "Size";
}
...
}

Then I could get/set the int HatUserControl.Size via
HatSelectionRequirement.Value
Jul 23 '07 #1
7 1203
Andy Bell wrote:
Can this be done via .net generics? How? The % signs below are just
to show how I want to do it, I realise they're not valid syntax.

public abstract class BaseSelectionRequirement {
...
protected Type mControlType;
protected string mFieldName;
protected Type mFieldType;
protected UserControl mControl;
...

public %mFieldType% Value {
get {
return ( ( %mControlType% ) mControl ).%mFieldName%;
}
set {
( ( %mControlType% ) mControl ).%mFieldName% = value;
}
}
}

So, say my descended class was:

public class HatSelectionRequirement : BaseSelectionRequirement {
public HatSelectionRequirement( ) {
mControlType = HatUserControl;
mFieldType = typeof( Int32 );
mFieldName = "Size";
}
...
}

Then I could get/set the int HatUserControl.Size via
HatSelectionRequirement.Value
THat's not the area where generics should be used. Generics should be
used to generalize a piece of algoritmic code by making the containing
class generic. THings like the fieldname aren't producable in generics,
generics is solely about types.

First of all, I'd like to recommend to you to NOT use protected fields
for members. Use private fields and protected properties. This allows
you to obtain the encapsulation that's often needed.

There's another problem with the design: there's a hard reference to
the control the object works on. This is odd to me, wouldn't it be
better to have a class which can work with any object of a given
control type?

I was half-way rewriting your abstract-nonabstract class tandem with a
property descriptor approach when it became really awkward, because:
where is the control instance passed in? If you want to read a value
from a live control, you have to pass it in. In your code that's not
done anywhere so I don't know how you want to do that.

The context of your code is also not very clear, so a good anwser is
abit hard to give.

FB
--
------------------------------------------------------------------------
Lead developer of LLBLGen Pro, the productive O/R mapper for .NET
LLBLGen Pro website: http://www.llblgen.com
My .NET blog: http://weblogs.asp.net/fbouma
Microsoft MVP (C#)
------------------------------------------------------------------------
Jul 23 '07 #2
Hi Andy,

I suggest you define the BaseSelectionRequirement class as a generic class.
As for the implementation of the Value property, we don't know either the
field name or its type until at run time. So we need to use reflection to
get/set the field's value at run time.

The following is a sample.

public class BaseClass<mControlType,mFieldType>
{
protected string mFieldName;
protected UserControl mControl;

public mFieldType Value
{
get
{
PropertyDescriptor pd =
TypeDescriptor.GetProperties(mControl)[mFieldName];
if (pd != null)
{
return (mFieldType)pd.GetValue(mControl);
}
else
{
return default(mFieldType);
}

}
set
{
PropertyDescriptor pd =
TypeDescriptor.GetProperties(mControl)[mFieldName];
if (pd != null)
{
pd.SetValue(mControl, value);
}
}
}
}
public class DerivedClass:BaseClass<UserControl,Int32>
{
private UserControl uc = new UserControl();
public DerivedClass()
{
this.mFieldName = "Height";
this.mControl = uc;
}

}

Hope this helps.
If you have any question, please feel free to let me know.

Sincerely,
Linda Liu
Microsoft Online Community Support

==================================================
Get notification to my posts through email? Please refer to
http://msdn.microsoft.com/subscripti...ult.aspx#notif
ications.

Note: The MSDN Managed Newsgroup support offering is for non-urgent issues
where an initial response from the community or a Microsoft Support
Engineer within 1 business day is acceptable. Please note that each follow
up response may take approximately 2 business days as the support
professional working with you may need further investigation to reach the
most efficient resolution. The offering is not appropriate for situations
that require urgent, real-time or phone-based interactions or complex
project analysis and dump analysis issues. Issues of this nature are best
handled working with a dedicated Microsoft Support Engineer by contacting
Microsoft Customer Support Services (CSS) at
http://msdn.microsoft.com/subscripti...t/default.aspx.
==================================================

This posting is provided "AS IS" with no warranties, and confers no rights.

Jul 23 '07 #3
Linda Liu [MSFT] wrote:
Hi Andy,

I suggest you define the BaseSelectionRequirement class as a generic
class. As for the implementation of the Value property, we don't know
either the field name or its type until at run time. So we need to
use reflection to get/set the field's value at run time.
That is exactly what I needed. It was the PropertyDescriptor that was
eluding me. Thank you!
Jul 24 '07 #4

"Andy Bell" <an************@newsgroup.nospamwrote in message
news:OE**************@TK2MSFTNGP03.phx.gbl...
Linda Liu [MSFT] wrote:
>Hi Andy,

I suggest you define the BaseSelectionRequirement class as a generic
class. As for the implementation of the Value property, we don't know
either the field name or its type until at run time. So we need to
use reflection to get/set the field's value at run time.

That is exactly what I needed. It was the PropertyDescriptor that was
eluding me. Thank you!
You should get a big performance improvement by defining "open" delegate
types:

mFieldType PropertyGetter<mControlType>(mControlType that);
void PropertySetter<mControlType>(mControlType that, mFieldType value);

and instantiating them using Delegate.CreateDelegate the results of
PropertyInfo.GetGetMethod and PropertyInfo.GetSetMethod, respectively, the
first time they are needed. Reflection is slow, if you can manage to avoid
using Invoke then you'll only pay the reflection cost the first time, when
you set up the delegates.

Highly recommended to define methods like:

class MissingAccessors<T{
static T PropertyNotGettable(object that) { throw new
NotSupportedException(); }
static void PropertyNotSettable(object that, T value) { throw new
NotSupportedException(); }
}

and use these to fill in your delegate members if reflection fails.
Jul 24 '07 #5
Hi Ben,

Thank you very much for your sharing!

I'm interested in your solution, but I couldn't understand it fully.

If possible, could you please give us a complete sample code?

Thank you for your time!

Sincerely,
Linda Liu
Microsoft Online Community Support

Jul 26 '07 #6

"Linda Liu [MSFT]" <v-****@online.microsoft.comwrote in message
news:MU**************@TK2MSFTNGHUB02.phx.gbl...
Hi Ben,

Thank you very much for your sharing!

I'm interested in your solution, but I couldn't understand it fully.

If possible, could you please give us a complete sample code?

Thank you for your time!
Something like this (not compile tested, but at least 99% there):

internal class MissingAccessors<T{
static T PropertyNotGettable(object that) { throw new
NotSupportedException(); }
static void PropertyNotSettable(object that, T value) { throw new
NotSupportedException(); }
}

public class ArbitraryPropertyProxy<mControlType, mFieldType>
{
public delegate mFieldType PropertyGetter(mControlType that);
public delegate void PropertySetter(mControlType that, mFieldType
value);

public readonly PropertyGetter getFrom;
public readonly PropertySetter setOnto;

public ArbitraryPropertyProxy(PropertyInfo pi)
{
if (pi.PropertyType != mFieldType) throw new ArgumentException();
try {
getFrom =
(PropertyGetter)Delegate.CreateDelegate(typeof(Pro pertyGetter),
pi.GetGetMethod());
}
catch {
getFrom = MissingAccessors<mFieldType>.PropertyNotGettable;
}
try {
setOnto =
(PropertySetter)Delegate.CreateDelegate(typeof(Pro pertySetter),
pi.GetSetMethod());
}
catch {
getFrom = MissingAccessors<mFieldType>.PropertyNotSettable;
}
}
}

public class PropertyLateBinder<mControlType, mFieldType>
{
private readonly static Dictionary<string,
ArbitraryPropertyProxy<mControlType, mFieldType>cachedProps = new
Dictionary<string, ArbitraryPropertyProxy<mControlType, mFieldType>>();

public static ArbitraryPropertyProxy<mControlType, mFieldType>
BindProperty(string propName)
{
ArbitraryPropertyProxy<mControlType, mFieldTypeproxy;
if (!cachedProps.TryGetValue(propName, out proxy)) {
try {
PropertyInfo pi =
typeof(mControlType).GetProperty(propName);
if (pi != null)
proxy = new ArbitraryPropertyProxy<mControlType,
mFieldType>(pi);
}
catch {}
cachedProps[propName] = proxy;
}
return proxy;
}

public static mFieldType Get(mControlType instance, string propName) {
ArbitraryPropertyProxy<mControlType, mFieldTypeproxy =
BindProperty(propName);
if (proxy == null) throw new ArgumentException("propName");
return proxy.getFrom(instance);
}

public static void Set(mControlType instance, string propName,
mFieldType newValue) {
ArbitraryPropertyProxy<mControlType, mFieldTypeproxy =
BindProperty(propName);
if (proxy == null) throw new ArgumentException("propName");
proxy.setOnto(instance, value);
}
}

void ChangeColor(Form f, Color c, string whichColor) {
foreach (Control c in f.Controls)
PropertyLateBinder<Control, Color>.Set(c, whichColor, c);
}

ChangeColor(this, Color.Black, "BackColor");
ChangeColor(this, Color.Red, "ForeColor");

Imagine that whichColor could be a dropdown list or something like that, so
it's not feasible to do early binding.
Aug 2 '07 #7
Hello Ben,

Thank you very much for your great code!

It will definitly improve the performance. And I think it benefit all of us.

Thank you again for your support of our MSDN managed Newsgroup!

Sincerely,
Linda Liu
Microsoft Online Community Support

Aug 6 '07 #8

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

27 posts views Thread by Bernardo Heynemann | last post: by
2 posts views Thread by Mr.Tickle | last post: by
23 posts views Thread by Luc Vaillant | last post: by
5 posts views Thread by anders.forsgren | last post: by
9 posts views Thread by sloan | last post: by
1 post views Thread by Vladimir Shiryaev | last post: by
13 posts views Thread by rkausch | last post: by

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.