Looking to make something like a delegate...

M

matsi.inc

I am looking to make something like a delegate that i can use in my
projects but am having a hard time getting started.

The behavior I am most interested in is how a delegate changes it's
Invoke method dynamically to match the arguments supplied to it when it
is defined. For example...


public delegate void MyDelegate(string myString, int myInt);

MyDelegate myDel = new MyDelegate(my.Target);


When I look at the Invoke method for myDel, you see...

myDel.Invoke(string myString, int myInt);

What I am ultimately looking to do is override the Invoke method of a
delegate but being that the Delegate class is locked, I can't just do
it the easy way.

My ultimate goal is to be able to pass a method invocation as a
parameter without it being invoked. As an example...

... using the delegate above...

MyAssembly.MyClass cls = new MyAssembly.MyClass();
MyDelegate myDel = new MyDelegate(cls.targetMethod);
MyAssembly.MyClass2 cls2 = new MyAssembly.MyClass2();
cls2.MyMethod(myDel("How old are you?", 0));

When this is run, the MyMethod on cls2 will use reflection to determine
the origin of the delegate, extract the parameter values, and invoke
the method. This is what I would like to do.

Even to understand/learn how a delegate definition allows for a
variable number of parameters to be defined, and then turn around and
create an Invoke method on the delegate that matches these parameters
would be a great deal of help.

Any help, suggestions, alternatives would be greatly appreciated.
 
J

Jon Shemitz

My ultimate goal is to be able to pass a method invocation as a
parameter without it being invoked. As an example...

... using the delegate above...

MyAssembly.MyClass cls = new MyAssembly.MyClass();
MyDelegate myDel = new MyDelegate(cls.targetMethod);
MyAssembly.MyClass2 cls2 = new MyAssembly.MyClass2();
cls2.MyMethod(myDel("How old are you?", 0));

When this is run, the MyMethod on cls2 will use reflection to determine
the origin of the delegate, extract the parameter values, and invoke
the method. This is what I would like to do.

Perhaps I'm missing something - why don't you just write cls2.MyMethod
to take a MyDelegate parameter?
 
S

Stoitcho Goutsev \(100\)

Hi,

when you declare a delegate the compiler actually generates a new class that
inherits from the MulticastDelegate class (which inherits from Delegate) and
declares the Invoke method with desired signature.

If by locked you mean sealed then no, neither Delegate nor MulticastDelegate
or the compiler generated class is not sealed. The only think is that you
cannot use them as a base class because the compiler doesn't allow you to.
The compiler allows you only to use its syntax for declaring delegates. On
the other hands for more configurable delegates you can use generics -
Generic Delegates.

For more info look at:
http://msdn2.microsoft.com/en-us/library/sx2bwtw7(VS.80).aspx
 
M

matsi.inc

Jon,

If I pass the delegate as a parameter then I cannot set the delegate's
parameter values. I would also have to pass an object array that
contains all the parameters and hope that they are in the correct
order, and the correct number of them.

Like...

cls2.MyMethod(myDel, new object[] { "How old are you?", 0 });

I have this working fine. But, you lose the benefit of intellisense
and making sure the parameters are typed and passed properly. That is
why i would like to be able to write...

cls2.MyMethod(myDel("How old are you?", 0));

What i want to do is just have the delegate functionality but when the
Invoke method is called, it does what I want it to do and not just
invoke the method the delegate is pointed to.

Make sense?
 
M

matsi.inc

Stoitcho,

Thanks for the information. I took a look at the generics and they
don't really solve my problem of what I am wanting to do. I may be
being picky here, but it just seems that I should be able to mimic the
behavior of anything provided in the framework exactly. What I like
about the delegate is that no matter how many parameters you define the
delegate with, the Invoke method matches those parameters. What i do
not like, is when you call Invoke, it automatically calls the target
method with the supplied parameter values. What i want to do is
intercept this invocation and do something else with the information
provided by the delegate invocation (method and parameter values). So,
i dont really want a delegate, but i want something that behaves like
one.

Any ideas?
 
B

Barry Kelly

Thanks for the information. I took a look at the generics and they
don't really solve my problem of what I am wanting to do. I may be
being picky here, but it just seems that I should be able to mimic the
behavior of anything provided in the framework exactly.

Delegate isn't part of the framework library though, it's more part of
the runtime. It's got magic behind it, such as verifiable use of 'ldftn'
IL instruction etc.
What I like
about the delegate is that no matter how many parameters you define the
delegate with, the Invoke method matches those parameters.

That's because it's a new class.
What i do
not like, is when you call Invoke, it automatically calls the target
method with the supplied parameter values. What i want to do is
intercept this invocation and do something else with the information
provided by the delegate invocation (method and parameter values).

So create a new delegate instance instead! Either do it in code with C#
(but that isn't automatic), or use System.Reflection.Emit to create a
new DynamicMethod that matches the delegate's prototype, and do your
interception there. You'll need to write a little compiler though; it's
not too difficult if you're familiar with that kind of thing.

If you're talking about something like intercepting all calls to all
delegates of a given type across the system, then no, you can't do
something like that (it would be a security risk too).

-- Barry
 
W

William Stacey [C# MVP]

Then do your hook before you call the delegate. Then call the delegate.
Maybe you could expand on what your asking.

--
William Stacey [C# MVP]

| Stoitcho,
|
| Thanks for the information. I took a look at the generics and they
| don't really solve my problem of what I am wanting to do. I may be
| being picky here, but it just seems that I should be able to mimic the
| behavior of anything provided in the framework exactly. What I like
| about the delegate is that no matter how many parameters you define the
| delegate with, the Invoke method matches those parameters. What i do
| not like, is when you call Invoke, it automatically calls the target
| method with the supplied parameter values. What i want to do is
| intercept this invocation and do something else with the information
| provided by the delegate invocation (method and parameter values). So,
| i dont really want a delegate, but i want something that behaves like
| one.
|
| Any ideas?
|
| Stoitcho Goutsev (100) wrote:
| > Hi,
| >
| > when you declare a delegate the compiler actually generates a new class
that
| > inherits from the MulticastDelegate class (which inherits from Delegate)
and
| > declares the Invoke method with desired signature.
| >
| > If by locked you mean sealed then no, neither Delegate nor
MulticastDelegate
| > or the compiler generated class is not sealed. The only think is that
you
| > cannot use them as a base class because the compiler doesn't allow you
to.
| > The compiler allows you only to use its syntax for declaring delegates.
On
| > the other hands for more configurable delegates you can use generics -
| > Generic Delegates.
| >
| > For more info look at:
| > http://msdn2.microsoft.com/en-us/library/sx2bwtw7(VS.80).aspx
| >
| >
| > --
| > HTH
| > Stoitcho Goutsev (100)
| >
| > | > >I am looking to make something like a delegate that i can use in my
| > > projects but am having a hard time getting started.
| > >
| > > The behavior I am most interested in is how a delegate changes it's
| > > Invoke method dynamically to match the arguments supplied to it when
it
| > > is defined. For example...
| > >
| > >
| > > public delegate void MyDelegate(string myString, int myInt);
| > >
| > > MyDelegate myDel = new MyDelegate(my.Target);
| > >
| > >
| > > When I look at the Invoke method for myDel, you see...
| > >
| > > myDel.Invoke(string myString, int myInt);
| > >
| > > What I am ultimately looking to do is override the Invoke method of a
| > > delegate but being that the Delegate class is locked, I can't just do
| > > it the easy way.
| > >
| > > My ultimate goal is to be able to pass a method invocation as a
| > > parameter without it being invoked. As an example...
| > >
| > > ... using the delegate above...
| > >
| > > MyAssembly.MyClass cls = new MyAssembly.MyClass();
| > > MyDelegate myDel = new MyDelegate(cls.targetMethod);
| > > MyAssembly.MyClass2 cls2 = new MyAssembly.MyClass2();
| > > cls2.MyMethod(myDel("How old are you?", 0));
| > >
| > > When this is run, the MyMethod on cls2 will use reflection to
determine
| > > the origin of the delegate, extract the parameter values, and invoke
| > > the method. This is what I would like to do.
| > >
| > > Even to understand/learn how a delegate definition allows for a
| > > variable number of parameters to be defined, and then turn around and
| > > create an Invoke method on the delegate that matches these parameters
| > > would be a great deal of help.
| > >
| > > Any help, suggestions, alternatives would be greatly appreciated.
| > >
|
 
J

Jon Shemitz

If I pass the delegate as a parameter then I cannot set the delegate's
parameter values. I would also have to pass an object array that
contains all the parameters and hope that they are in the correct
order, and the correct number of them.

Like...

cls2.MyMethod(myDel, new object[] { "How old are you?", 0 });

Well, no, you don't have to do this. You could pass

(MyDelegate delegateToCall,
string delegateString, int delegateInt);

and then call delegateToCall(delegateString, int delegateInt);
What i want to do is just have the delegate functionality but when the
Invoke method is called, it does what I want it to do and not just
invoke the method the delegate is pointed to.

Alternatively, if what you want is a single, self-contained
'delegate-like' reference that you can fire when something happens,
you can always just take a

delegate void SelfContained();

parameter, and pass it an anonymous method that captures the
appropriate parameters:

cls2.MyMethod(delegate
{ cls.targetMethod("How old are you?", 0); });

targetMethod is NOT called when you pass the delegate to cls2.MyMethod
- but it will be called when you invoke the SelfContained parameter.
 
M

matsi.inc

Jon,

This has definitely gotten me closer to the solution I am looking for.
But I am starting to feel like I need to explain what my ultimate goal
is b/c I think I may be looking at this wrong. Here is what i would
ultimately like to see, or something close...

First, I have a class with a login method and delegate... (The
SecurityToken is an object that contains details about the login
attempt)

public MySecurityClass
{
public delegate LoginDelegate(string Username, string Password);

public SecurityToken Login(string Username, string Password)
{ // do login }

}

Now, I need to provide this method via a web service, instead of making
a web method for each method in my MySecurityClass class, I want a
generic method that accepts what I am calling a 'Method Invocation'
(the method and parameter values used to execute the method... like
what is provided in the anonymous method you showed me). So, when the
webmethod gets this 'Method Invocation', i can use reflection to find
the assembly it belongs to, execute the method, and return a value is
needed (one of the reasons I have been looking at a delegate). So,
something like this...

[WebMethod]
public object InvokeMethod(??? MyMethodInvocation)
{ // reflect to process method }

Finally, on the front-end, what i would like to be able to do is type
the following code to execute the action...

MySecurityClass security = new MySecurityClass();
LoginDelegate loginDel = new LoginDelegate(security.Login);
MyWebService webService = new MyWebService();
SecurityToken token = (SecurityToken) webService.InvokeMethod(
loginDel("MyUsername", "MyPassword") );

By doing this, I get the benefit of Intellisense and typed parameters
for my login method. Also, if my login method changes, i will be
alerted during compilation. One thing I do not want to have to do is
code a separate web method for each action in my action class.

I was looking strongly at delegates because of the way it is able to
alter it's Invoke method parameter signature based on how it is
declared and felt that this is how I should approach this. But now,
after reading these responses, I am starting to think I am going about
this the wrong way. So, hopefully, you see what I am trying to do
here. If not, let me know what you don't see so i can try to give you
a bit more detail. Otherwise, any help in trying to solve this, or
getting something close, would be great!

Also, thanks to everyone else who has chimed in!

Jon said:
If I pass the delegate as a parameter then I cannot set the delegate's
parameter values. I would also have to pass an object array that
contains all the parameters and hope that they are in the correct
order, and the correct number of them.

Like...

cls2.MyMethod(myDel, new object[] { "How old are you?", 0 });

Well, no, you don't have to do this. You could pass

(MyDelegate delegateToCall,
string delegateString, int delegateInt);

and then call delegateToCall(delegateString, int delegateInt);
What i want to do is just have the delegate functionality but when the
Invoke method is called, it does what I want it to do and not just
invoke the method the delegate is pointed to.

Alternatively, if what you want is a single, self-contained
'delegate-like' reference that you can fire when something happens,
you can always just take a

delegate void SelfContained();

parameter, and pass it an anonymous method that captures the
appropriate parameters:

cls2.MyMethod(delegate
{ cls.targetMethod("How old are you?", 0); });

targetMethod is NOT called when you pass the delegate to cls2.MyMethod
- but it will be called when you invoke the SelfContained parameter.
 
J

Jon Shemitz

instead of making
a web method for each method in my MySecurityClass class, I want a
generic method that accepts what I am calling a 'Method Invocation'
(the method and parameter values used to execute the method... like
what is provided in the anonymous method you showed me). So, when the
webmethod gets this 'Method Invocation', i can use reflection to find
the assembly it belongs to, execute the method, and return a value is
needed (one of the reasons I have been looking at a delegate). So,
something like this...

I don't understand why you want to use Reflection to find the assembly
- isn't it enough just to make the deferred call?

Fwiw, anynonymous methods can return results.
 
M

matsi.inc

Jon,

I am figuring that i need to use reflection to invoke the method b/c I
need to send the 'Method Invocation' (my term) through a web service to
an app server before executing the method. I've tried multiple ways to
pass an anonymous method from a client to a web service but have been
unsuccessful. I have even tried forcing the delegate you suggested,
passing the action in the anonymous method, but the webservice does not
see it as a typed delegate and errors when I try to send the call.

I guess my real problem now is getting it to the app server. By using
your examples, I was able to get all of this to work when my business
login and client are on the same machine. My problem is that they
never are in production.

Any ideas on how to get this method info and parameter values over the
to app server and still keep the client coding the way it is?
 
J

Jon Shemitz

I am figuring that i need to use reflection to invoke the method b/c I
need to send the 'Method Invocation' (my term) through a web service to
an app server before executing the method. I've tried multiple ways to
pass an anonymous method from a client to a web service but have been
unsuccessful. I have even tried forcing the delegate you suggested,
passing the action in the anonymous method, but the webservice does not
see it as a typed delegate and errors when I try to send the call.

I guess my real problem now is getting it to the app server. By using
your examples, I was able to get all of this to work when my business
login and client are on the same machine. My problem is that they
never are in production.

Any ideas on how to get this method info and parameter values over the
to app server and still keep the client coding the way it is?

Oh, I'm sorry. I totally did not pick up on the fact that you want to
send a method spec and arguments to a remote machine. I suppose I
should have, but I didn't.

About all I can suggest is that you wrap your single web entry point
in a set of strongly typed client-side methods. These would allow you
to use Intellisense &c, and would then package their arguments and a
method name into an XML packet that you send to the remote method.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top