Jalf

Let's say I have the following:

class Foo {
private int myInt;
public void SetInt(int i){myInt = i;}
}

And then somewhere else, I have this:
delegate void MyDelegate(int); // Define a delegate that matches the signature of the Foo.SetInt function
class Bar{
void DoStuff(MyDelegate someDelegate){ .... } // A function taking the delegate as an argument
}

Now I can easily pass SetInt as a delegate to the DoStuff function, no problem there.

But what if I'd used a set property instead of the SetInt function, like so
class Foo {
private int myInt;
public int MyInt{
set {myInt = value;}
}
}

Is there any way I can then pass the MyInt property as a delegate to another function

I suppose I could do it by wrapping it in an anonymous delegate like this:
someBar.DoStuff(delegate(int i){MyInt = i;});

but ideally I'd like to be able to pass it directly at the call site, without having to squeeze a custom delegate in between them.

My problem is that I have a number of classes with get- and set properties for all their data members, and I'd like to be able to make a generic function that took any set property from any of the classes, and updated it. (I could make every single set property do the same, but then I'd have to duplicate this logic 20 or so times... I'd rather have it in a single generic function, since it has to do a bit more internal housekeeping than just updating the corresponding private data member.)

As a little bonus question, what, if anything, is the difference between these two lines of code
someBar.DoStuff(myFoo.SetInt);
and
someBar.DoStuff(new MyDelegate(myFoo.SetInt));

The latter version seems to be more common, but the former seems to work just as well, as far as I can see. Are there any more subtle differences I'm not aware of


Re: Visual C# Language Passing properties as delegates

Figo Fei - MSFT

Hi, Jalf

The Microsoft .NET Framework exposes a callback function mechanism using delegates. Unlike callback mechanisms used in other platforms, such as unmanaged C++, delegates ensure that the callback method is type-safe. Delegates also integrate the ability to call multiple methods serially and support the calling of static methods as well as instance methods.

Delegates are similar to function pointers in C++, except delegates are type-safe and secure. So it is nature to understand why someBar.DoStuff(myFoo.SetInt) can do the same thing as someBar.DoStuff(new MyDelegate(myFoo.SetInt)).






Re: Visual C# Language Passing properties as delegates

Figo Fei - MSFT

Jalf wrote:

My problem is that I have a number of classes with get- and set properties for all their data members, and I'd like to be able to make a generic function that took any set property from any of the classes, and updated it. (I could make every single set property do the same, but then I'd have to duplicate this logic 20 or so times... I'd rather have it in a single generic function, since it has to do a bit more internal housekeeping than just updating the corresponding private data member.)

If you want to update the class members, and to do a bit more internal housekeeping, then properties provide! So what special you want it to






Re: Visual C# Language Passing properties as delegates

Jalf

Well, I have 15 or so classes, each with several properties. For each of the properties, I need to do the same things. I really do not want to duplicate that code 30-40 times.

What I need to do is update two classes in sync. That is, when I set a property on one class, I have to add the object to another class's collection. And vice versa.

That also means I can't let the set properties do the housekeeping, even if I wanted to duplicate the code. I need to pass in extra parameters telling it which property on which class instance should be updated. And besides, the set property is accessed occasionally by another library, where none of this logic should be performed.

Rather, I'd thought about making the set property internal (so it can't be accessed from outside), and then provide a helper class with a generic function that could be given as argument which properties it should update, as well as the relevant objects, and update them properly. That could easily be done with delegates if I'd used a setter function instead of a property. (But the other library insists that they must be properties, not functions so that's out of the question) So is there any sneaky way to do the same with properties

"Delegates are similar to function pointers in C++, except delegates are type-safe and secure. So it is nature to understand why someBar.DoStuff(myFoo.SetInt) can do the same thing as someBar.DoStuff(new MyDelegate(myFoo.SetInt))."
Does that mean that when I don't do the 'new' bit, it doesn't create a delegate What exactly does it do then (Since C# doesn't have function pointers)
I thought it implicitly created a delegate in any case

Thanks, both of you. Some helpful stuff in here :)




Re: Visual C# Language Passing properties as delegates

Figo Fei - MSFT

Hi, Jalf

You could use an interface to implement this as well as delegate. Since your classes can all implement the same interface. In which way, you can use the same interface to maintain the members in different classes. But since you dont want to type many code, delegate may be prefered.

About the delegate question: As you use the delegate, it is not necessary to worry about that, and it is good for C# to provide programmers the convenience. Though the question is really a good and academic one, dealing with the internal implementation mechanism of the delegate param.






Re: Visual C# Language Passing properties as delegates

frederikm

Hi,

you can delegates for this, but it's not really an elegant solution.

however, you can do something else, which is a bit cleaner in my book

your class requires a number of properties for an external library

public class Class1 {

private int _myProperty1;
private int _myProperty2;

public int MyProperty2 {
get {return _myProperty2;}
set {_myProperty2 = value;}
}

public int MyProperty1 {
get {return _myProperty1;}
set {_myProperty1 = value;}
}

}

However, you want to point a delegate to a setter function

internal void SetProperty1(int value) {
_myProperty1 = value;
}

internal void SetProperty2(int value) {
_myProperty2 = value;
}

If you implement internal voids as setters, these are but acceptable to the types in the assembly, providing a cleaner interface for external libraries.
and now you have a target for your delegates

However, a generic function to set values of a class kind of raises my eyebrows...

Could you not implement an interface to do this
Could you post some code as to what you are trying to do

anyway, hope this helps






Re: Visual C# Language Passing properties as delegates

Jalf

Hi, both of you. Thanks for your replies. :)

Figo Fei:
"About the delegate question: As you use the delegate, it is not necessary to worry about that, and it is good for C# to provide programmers the convenience. Though the question is really a good and academic one, dealing with the internal implementation mechanism of the delegate param."

Yeah, I know it's not usually necessary to worry about any differences between the two (since as far as I've noticed, they do the same thing), but I'd still like to understand if there are any differences under the hood. I guess it is an academic question, but I always prefer to know exactly how things work. Makes for fewer nasty surprises later on. ;)
If they are exactly the same, I'll go with the cleaner syntax, but if there are subtle differences, I'd like to know about them before I run into weird problems. ;)

frederikm: I know it might be a bit unconventional to use generic functions for this (It's a bit of an experiment in any case, so part of the motivation is simply to find out how well it works. Generics seem to be underused for a lot of purposes, so since I have some experience with C++ template metaprogramming, I'm a bit curious about how far you can push generics to achieve similar tricks.)

You may be right, it's not the most elegant solution to pursue. But bear with me, think of it as an experiment. ;)

Anyway, a bit more detail:
We're using NHibernate to map classes to database tables, and uses get/set properties to map to table columns.

One limitation is regarding one-to-many relations.

That is, class A has a property (let's call it Parent) containing a reference to B.
And class B holds a collection (call it Children) of A's.

Obviously, I'd like to ensure that when a new child is added to B, its parent is set appropriately, it is removed from its previous parent, and so on.

Next problem (which makes interfaces tricky to use), each class may participate in multiple one-to-many relations.

A class may contain several different collections of "children", or it may have multiple properties pointing to "parents".


Ok, what I'd originally intended to do was something like this:
Say we have two classes, A and B with such a one-to-many relationship between them.

class A {
public B Parent{
get { ... } // The rest of the app obviously needs to use the getter, so that's public
internal set { ... } // Make the setter internal so it can only be accessed from this assembly (and NHibernate), but not from the rest of the app.
}
}

class B {
public ReadOnlyCollection<A> Children {
get { ... } // The rest of the app needs to be able to read the list, but we dont want anyone outside to modify it, so I'm only exposing a ReadOnlyCollection
}

internal IList<A> ChildrenList { // NHibernate has to be able to access and manipulate the list, so expose an IList with internal scope
get { ... }
set { ... }
}

}

Now, I'd imagined creating a helper class to use when adding new children. It'd obviously need to be told which objects to work on, as well as which properties on each of the objects represent the parent/child relationship:

class Helper {
public static void SetChild<ParentType, ChildType>(ChildReferenceDelegate<ChildType> childrenProperty, ParentReferenceDelegate<ParentType> parentProperty)
{ ... }
}

then you could call it something like this:
Helper.SetChild<B, A>(parent.Children, child.Parent);

and that would be the only way you could change the A.Parent or B.Children fields from other assemblies, because the set properties are internal.

The reason I'd rather avoid having to rely too much on changes in the classes A and B is because I don't have just two of them. There's quite a few more, and as I said, they have a variable number of properites I need to handle this problem on, so it'd be a pain to maintain too much get/set logic in all these. And because they have to match the database layout, they may change or get properties added to them, which would then bypass my parent/child checks

On the other hand, a generic function such as the one I outlined would work with any of the properties on any of the classes. The only requirement would be that any type passed as ParentType has a property exposing a ReadOnlyCollection of type ChildType, and that ChildType exposes a property pointing to an object of ParentType.
Nice and generic and much simpler to maintain.
At least in theory... ;)

Cheers :)




Re: Visual C# Language Passing properties as delegates

frederikm

Jalf

First off, kudos for using NHibernate!
Been using it on a lot of personal projects and absolutely love it...!

I do believe that delegates are not the way to implement this,

what you could do is the following:

class Helper<ParentType, ChildType> {
public static void SetChild (ParentType parent, PropertyInfo childrenProperty, ChildType child, PropertyInfo parentProperty)
{

//set parent on child
parentProperty.SetValue(child, parent, null);

//add child to parent collection
IList list = (IList) childrenPropery.GetValue(parent);
list.Add(child);

}
}

This is using the PropertyInfo class from the reflection namespace
http://msdn2.microsoft.com/en-us/library/system.reflection.propertyinfo.aspx

Also, you can eliminate the internal exposure of your IList by mapping you Bag (if that's what you are using ;)) on the private field instead of the public,
but that's just a personal preference.. elegant code and all ;)

Hope this helps!






Re: Visual C# Language Passing properties as delegates

Lowendahl

So you are saying that NH don't have proper inverse managament but you need to write the inverses handling yourself

My suggestion is to change O/R mapper if that's the case to some who support inverse management. Like NPersist www.puzzleframework.com

Otherwise you could more effectivley use Reflection handle the inverse management instead of delegates / interfaces.






Re: Visual C# Language Passing properties as delegates

frederikm

Hi, NHibernate does have proper inverse management, but then you would need to use different relationships...

-many to many

class a {

[Bag(20, Access = "field", Cascade = CascadeStyle.AllDeleteOrphan, Table = "A_B", Name = "_Items")]
[
Key(21, Column = "Id_A")]
[
ManyToMany(22, ClassType = typeof(Phone), Column = "Id_B")]
private IList _Items = new ArrayList();

}

class b{}

This gives you a table A_B with the respective id's

- One to many

class c {
[Bag(6, Access = "field", Name = "_Answers", Cascade = CascadeStyle.All)]
[
Key(7, Column = "Id_C")]
[
OneToMany(8, ClassType = typeof(d))]
private IList _Answers = new ArrayList();
}

class d{}

this means that in the mapping of class d an the id of the parent class c is included

Hope this helps






Re: Visual C# Language Passing properties as delegates

Lowendahl

And that will update a childs parent column in the db if the child get's moved

What happens if you update the parents id, will it update that column in all children as well






Re: Visual C# Language Passing properties as delegates

frederikm

Hi

yes on both accounts :)

however, this does not include the Parent property on the child object,
but a tutorial on that can be found in the nhibernate docs..

on the id's: I personnaly prefer to use the db id (identity setting in nhibernate)

HTH






Re: Visual C# Language Passing properties as delegates

Lowendahl

So a limping inverse management then ;) NPersist manages to handle the object references as well as the update in the database.




Re: Visual C# Language Passing properties as delegates

frederikm

hi

don't get me wrong, nhibernate can manage it all, I just don't use all of it ;).

To me, an id is an id, and thus can not be changed.






Re: Visual C# Language Passing properties as delegates

Alois

Hi Jalf,

you can do it by using Visual Basic directly. Since the CLR stands for Common Language Runtime you will have no probs doing it this way ;-).

A C# way is described here:
http://geekswithblogs.net/akraus1/archive/2006/02/10/69047.aspx

Hope this helps a bit.

Yours,
Alois Kraus