471,354 Members | 1,539 Online
Bytes | Software Development & Data Engineering Community
Post +

Home Posts Topics Members FAQ

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

How to hook up EventHandler or Delegate to UserControl thru Reflec

Hi

I have an Assembly that has various usercontrols that all implemnet
an Interface

The Interface

public interface ISettings
{
bool SaveSettings();
}
I then have a test pgm that will loop thru the asssmbly and find all classes
that implement the ISettings interface. I then display all the UserControls
on a Form

Assembly asm = Assembly.LoadFrom(@"C:\myUserContro.dll");
// Walk through each type in the assembly looking for our
class
foreach (Type type in asm.GetTypes())
{
if (type.IsClass == true )
{
bClass = false;
foreach (Type interfaceType in type.GetInterfaces())
{
if (interfaceType.FullName.Contains("ISettings"))
{
bClass = true;
break;
}
}

if(bClass)
{
Control control = Activator.CreateInstance(type)
as Control;
xtraTabControl1.TabPages.Add();

xtraTabControl1.TabPages[xtraTabControl1.TabPages.Count - 1].Text =
type.FullName;

xtraTabControl1.TabPages[xtraTabControl1.TabPages.Count-1].Controls.Add(control);
}
}
This is all fine
The question is on the form where I create the UserControls I have a "SAVE"
button. When I hit the SAVE button I want to fire all the interface method
"SaveSettings" from all the UserControls.

What is the best way to do that???

Thanks
Sep 4 '08 #1
22 2264
On Thu, 04 Sep 2008 14:21:01 -0700, sippyuconn
<si********@newsgroup.nospamwrote:
[...]
The question is on the form where I create the UserControls I have a
"SAVE"
button. When I hit the SAVE button I want to fire all the interface
method
"SaveSettings" from all the UserControls.

What is the best way to do that???
I don't think reflection as anything to do with the question. As far as
what's the "best way", that's not for us to say. But one option might be
to create a delegate and add the SaveSettings() method for each
implementor to the delegate. For example:

private Func<boolSaveSettingsHandlers;

// when adding a UserControl:
UserControl control = ...;
ISettings settings = (ISettings)control;

SaveSettingsHandlers += settings.SaveSettings;

// when you want all the settings to be saved, invoke the delegate:
SaveSettingsHandlers();

Of course, it begs the question as to why the method returns a bool. If
you actually want to use that in some way, you'll want to change the
invocation. For example:

foreach (Func<boolhandler in
SaveSettingsHandlers.GetInvocationList())
{
if (!handler())
{
// return/display error, whatever
}
}

Pete
Sep 4 '08 #2
On Sep 4, 2:41*pm, "Peter Duniho" <NpOeStPe...@nnowslpianmk.com>
wrote:
On Thu, 04 Sep 2008 14:21:01 -0700, sippyuconn *
I don't think reflection as anything to do with the question. *As far as *
what's the "best way", that's not for us to say. *But one option might be *
to create a delegate and add the SaveSettings() method for each *
implementor to the delegate. *For example:
Of course, it begs the question as to why the method returns a bool. *If *
you actually want to use that in some way, you'll want to change the *
invocation. *For example:
yeah I guess I second Peter on this. I find that a delegate is like a
super "GOTO" statement, that you can 'throw' to call another function
that's not even aware of what's going on in the code that throws. A
global GOTO.

The other option, equally bad but easier to write, is of course to use
the old standby of a 'global' boolean (to the namespace, as C# has no
true global variables). When the global boolean is changed, an if
statement somewhere in your active code takes over. And of course the
related solution of using enums and case statements, which is how
classic Windows works.

I think the problem though is that in C# Winforms code and data and
not separated. I'm looking forward to studying WPF in a few months
and seeing how they supposedly solved the problem by separating code
and data.

RL
Sep 4 '08 #3
I mention reflection because the interface is in a third party assemble that
I don't have access to code so I needed to use reflection to get at the
interface and Method

But I am stuck - how to tie the Class or Methods of Class using relection to
extract - to then tie to Delegate
public delegate bool CustomSaveHandler();
Assembly asm = Assembly.LoadFrom(@"C:\myassembly.dll");
// Walk through each type in the assembly looking for our
class
foreach (Type type in asm.GetTypes())
{
if (type.IsClass == true )
{
bClass = false;
foreach (Type interfaceType in type.GetInterfaces())
{
if (interfaceType.FullName.Contains("ISettings"))
{
bClass = true;
break;
}
}

if(bClass)
{
Control control = Activator.CreateInstance(type)
as Control;
xtraTabControl1.TabPages.Add();

xtraTabControl1.TabPages[xtraTabControl1.TabPages.Count - 1].Text =
type.FullName;

xtraTabControl1.TabPages[xtraTabControl1.TabPages.Count-1].Controls.Add(control);

MethodInfo typemethod =
type.GetMethod("SaveSettings");

?????

"raylopez99" wrote:
On Sep 4, 2:41 pm, "Peter Duniho" <NpOeStPe...@nnowslpianmk.com>
wrote:
On Thu, 04 Sep 2008 14:21:01 -0700, sippyuconn
I don't think reflection as anything to do with the question. As far as
what's the "best way", that's not for us to say. But one option might be
to create a delegate and add the SaveSettings() method for each
implementor to the delegate. For example:
Of course, it begs the question as to why the method returns a bool. If
you actually want to use that in some way, you'll want to change the
invocation. For example:

yeah I guess I second Peter on this. I find that a delegate is like a
super "GOTO" statement, that you can 'throw' to call another function
that's not even aware of what's going on in the code that throws. A
global GOTO.

The other option, equally bad but easier to write, is of course to use
the old standby of a 'global' boolean (to the namespace, as C# has no
true global variables). When the global boolean is changed, an if
statement somewhere in your active code takes over. And of course the
related solution of using enums and case statements, which is how
classic Windows works.

I think the problem though is that in C# Winforms code and data and
not separated. I'm looking forward to studying WPF in a few months
and seeing how they supposedly solved the problem by separating code
and data.

RL
Sep 5 '08 #4
On Thu, 04 Sep 2008 19:38:02 -0700, sippyuconn
<si********@newsgroup.nospamwrote:
I mention reflection because the interface is in a third party assemble
that
I don't have access to code so I needed to use reflection to get at the
interface and Method

But I am stuck - how to tie the Class or Methods of Class using
relection to
extract - to then tie to Delegate
As demonstrated in my code example, once you have an instance of the class
(in my example, a UserControl that implements the interface...in your own
example, you've simply got the type Control) just cast it to the interface
and use the method from that.

In fact, since you named your Control instance variable the same as I
named my UserControl instance variable, the code is basically the same.

Pete
Sep 5 '08 #5
Dear sippyuconn,

You can call the Type.GetInterface() method to retrieve the interface, and
call Type.GetMethod() method to retrieve the "SaveSettings" method, then
call the Invoke() method to invoke the "SaveSettings" method.

For example, you can do something like this(I use a List<Control>
collection to store the UserControls in this example):

List<ControlctlsFromAsm = new List<Control>();

private void button1_Click(object sender, EventArgs e)
{
foreach (Control c in this.ctlsFromAsm)
{

c.GetType().GetInterface("ISettings").GetMethod("S aveSettings").Invoke(c,
null);
}
}

If any of this is unclear, please feel free to let me know.

Sincerely,
Zhi-Xin Ye
Microsoft Managed Newsgroup Support Team

Delighting our customers is our #1 priority. We welcome your comments and
suggestions about how we can improve the support we provide to you. Please
feel free to let my manager know what you think of the level of service
provided. You can send feedback directly to my manager at:
ms****@microsoft.com.

==================================================
Get notification to my posts through email? Please refer to
http://msdn.microsoft.com/en-us/subs...#notifications.

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://support.microsoft.com/select/...tance&ln=en-us.
==================================================
This posting is provided "AS IS" with no warranties, and confers no rights.

Sep 5 '08 #6
Reading these replies makes me wonder: is it possible to use
reflection to extract methods from .exe files? Not .DLL but
executables? I doubt it, because it would defeat the purpose of the
obfuscator, and/or why people distribute binary rather than source
code (to protect the IP in the source code), but I could be wrong.

Just curious.

RL
Zhi-Xin Ye [MSFT] wrote:
Dear sippyuconn,

You can call the Type.GetInterface() method to retrieve the interface, and
call Type.GetMethod() method to retrieve the "SaveSettings" method, then
call the Invoke() method to invoke the "SaveSettings" method.
Sep 5 '08 #7
On Sep 5, 9:27*am, raylopez99 <raylope...@yahoo.comwrote:
Reading these replies makes me wonder: *is it possible to use
reflection to extract methods from .exe files?
Yes.
>*Not .DLL but executables? *I doubt it, because it would defeat the purpose of the
obfuscator, and/or why people distribute binary rather than source
code (to protect the IP in the source code), but I could be wrong.
Not everyone wants to have to compile code before using it. Note that
using reflection to find methods isn't the same as decompilation,
although both are feasible on executables. Download RedGate Reflector
and have a look.

http://www.red-gate.com/products/reflector/

Jon
Sep 5 '08 #8
"raylopez99" <ra********@yahoo.comwrote in message
news:a9**********************************@a70g2000 hsh.googlegroups.com...
Reading these replies makes me wonder: is it possible to use
reflection to extract methods from .exe files? Not .DLL but
executables? I doubt it, because it would defeat the purpose of the
obfuscator, and/or why people distribute binary rather than source
code (to protect the IP in the source code), but I could be wrong.
For the record, there isn't much difference between .NET .exe and .dll
assemblies. For example, you can actually reference an .exe assembly from a
project as if it were a .dll library, and use the public classes/methods
within it as usual.
Sep 5 '08 #9
This is where my problem is - I cannot cast the Method because it is a
ThirdParty Assemble
public delegate bool CustomSaveHandler();
....

MethodInfo typemethod = type.GetMethod("SaveSettings");

I am trying to add the method to delegate by
but won't compile
Error 3 'typemethod' is a 'variable' but is used like a 'method'
CustomSaveHandler a = new CustomSaveHandler(typemethod);

or

CustomSaveHandler b;
b += new CustomSaveHandler(typemethod);

What is the way around this if I cannot cast the method ???

Thanks

"Peter Duniho" wrote:
On Thu, 04 Sep 2008 19:38:02 -0700, sippyuconn
<si********@newsgroup.nospamwrote:
I mention reflection because the interface is in a third party assemble
that
I don't have access to code so I needed to use reflection to get at the
interface and Method

But I am stuck - how to tie the Class or Methods of Class using
relection to
extract - to then tie to Delegate

As demonstrated in my code example, once you have an instance of the class
(in my example, a UserControl that implements the interface...in your own
example, you've simply got the type Control) just cast it to the interface
and use the method from that.

In fact, since you named your Control instance variable the same as I
named my UserControl instance variable, the code is basically the same.

Pete
Sep 5 '08 #10
On Sep 5, 1:54*pm, sippyuconn <sippyuc...@newsgroup.nospamwrote:
This is where my problem is - I cannot cast the Method because it is a
ThirdParty Assemble

public delegate bool CustomSaveHandler();
...

*MethodInfo typemethod = type.GetMethod("SaveSettings");

I am trying to add the method to delegate by
but won't compile
Error * 3 * * * 'typemethod' is a 'variable' but is used like a 'method' * * * *

CustomSaveHandler a = new CustomSaveHandler(typemethod);

or

CustomSaveHandler b;
b += new CustomSaveHandler(typemethod);

What is the way around this if I cannot cast the method ???
Use

b += (CustomSaveHandler)
Delegate.CreateDelegate(typeof(CustomSaveHandler), typemethod);

Jon
Sep 5 '08 #11
Sorry one more ??

I get an exception
Error binding to target method.

"Jon Skeet [C# MVP]" wrote:
On Sep 5, 1:54 pm, sippyuconn <sippyuc...@newsgroup.nospamwrote:
This is where my problem is - I cannot cast the Method because it is a
ThirdParty Assemble

public delegate bool CustomSaveHandler();
...

MethodInfo typemethod = type.GetMethod("SaveSettings");

I am trying to add the method to delegate by
but won't compile
Error 3 'typemethod' is a 'variable' but is used like a 'method'

CustomSaveHandler a = new CustomSaveHandler(typemethod);

or

CustomSaveHandler b;
b += new CustomSaveHandler(typemethod);

What is the way around this if I cannot cast the method ???

Use

b += (CustomSaveHandler)
Delegate.CreateDelegate(typeof(CustomSaveHandler), typemethod);

Jon
Sep 5 '08 #12
On Sep 5, 3:51*pm, sippyuconn <sippyuc...@newsgroup.nospamwrote:
Sorry one more ??

I get an exception
Error binding to target method.
That can happen for a number of reasons. Post a short but complete
program and we can try to work out why.
See http://pobox.com/~skeet/csharp/complete.html for more details.

Jon
Sep 5 '08 #13

public delegate bool CustomSaveHandler();

public partial class Form1 : Form
{

public Form1()
{
InitializeComponent();
LoadConfigurationUserControls();

}

private void LoadConfigurationUserControls()
{
bool bClass = false;

CustomSaveHandler a = null;
List<stringlist = new List<string>();
try
{
Assembly asm = Assembly.LoadFrom(@"C:\Mydll.dll");
// Walk through each type in the assembly looking for our
class
foreach (Type type in asm.GetTypes())
{
if (type.IsClass == true )
{
bClass = false;
foreach (Type interfaceType in type.GetInterfaces())
{
if (interfaceType.FullName.Contains("ISettings"))
{
bClass = true;
break;
}
}

if(bClass)
{
Control control = Activator.CreateInstance(type)
as Control;
xtraTabControl1.TabPages.Add();

xtraTabControl1.TabPages[xtraTabControl1.TabPages.Count - 1].Text =
type.FullName;

xtraTabControl1.TabPages[xtraTabControl1.TabPages.Count-1].Controls.Add(control);

MethodInfo typemethod =
type.GetMethod("SaveSettings");

a +=
(CustomSaveHandler)Delegate.CreateDelegate(typeof( CustomSaveHandler),
typemethod);

}
}
}
"Jon Skeet [C# MVP]" wrote:
On Sep 5, 3:51 pm, sippyuconn <sippyuc...@newsgroup.nospamwrote:
Sorry one more ??

I get an exception
Error binding to target method.

That can happen for a number of reasons. Post a short but complete
program and we can try to work out why.
See http://pobox.com/~skeet/csharp/complete.html for more details.

Jon
Sep 5 '08 #14
On Fri, 05 Sep 2008 05:54:09 -0700, sippyuconn
<si********@newsgroup.nospamwrote:
This is where my problem is - I cannot cast the Method because it is a
ThirdParty Assemble
I'm not sure I understand that statement. Are you trying to say that the
ISettings interface isn't known to your code that's doing the reflection?

If so, then I think you want this:

a +=
(CustomSaveHandler)Delegate.CreateDelegate(typeof( CustomSaveHandler),
control, typemethod);
Sep 5 '08 #15
On Sep 5, 5:14*pm, sippyuconn <sippyuc...@newsgroup.nospamwrote:
public delegate bool CustomSaveHandler();

public partial class Form1 : Form
<snip>

Okay, well that's not a *complete* example because you've only posted
half of the form's code. By the time you've made it complete it then
won't be short, because you're using a GUI for no particular reason.
Furthermore, you're loading an assembly we haven't got, so we can't
possibly test it.

Given the code you've actually written, however, here's the short but
complete code which would have saved me some time and immediately
given me code I could compile, run and fix:

using System;
using System.Reflection;

public class Settings
{
public bool SaveSettings()
{
Console.WriteLine("Called");
return true;
}
}

public delegate bool CustomSaveHandler();

public class Test
{
static void Main()
{
// Fetched dynamically in real code
Type clazz = typeof(Settings);
object instance = Activator.CreateInstance(clazz);
MethodInfo method = clazz.GetMethod("SaveSettings");

// This line throws an exception
CustomSaveHandler handler = (CustomSaveHandler)
Delegate.CreateDelegate(typeof(CustomSaveHandler),
method);

handler();
}
}

The fix is quite simple - you need a different overload for
CreateDelegate: the one which takes the target of the call as well:

CustomSaveHandler handler = (CustomSaveHandler)
Delegate.CreateDelegate(typeof(CustomSaveHandler),
instance, method);

Hope this helps - and please bear in mind the hints above next time
you want to demonstrate a problem on newsgroups.

Jon
Sep 5 '08 #16
On Sep 5, 2:54*am, "Pavel Minaev" <int...@gmail.comwrote:
>
For the record, there isn't much difference between .NET .exe and .dll
assemblies. For example, you can actually reference an .exe assembly froma
project as if it were a .dll library, and use the public classes/methods
within it as usual.

Thanks, that was interesting. From Jon's link I see that the tool at
RedGate assumes you do not use the 'obfuscator', otherwise, they would
not mention it (see %%% below).

From this I conclude that when in non-release, non-obfuscated code,
your .exe file is like a .dll file for .NET assemblies--I did not know
that.

RL
Use Reflector if you need to:

* Explore .NET assemblies in an easy-to-understand, natural way
* Understand the relationships between classes and methods
* Find where types are instantiated and exposed
%%% * Check that your code has been correctly obfuscated before
release %%% //so obfuscation will hide your code from this tool

Sep 5 '08 #17
Here is a complete sample

public interface ISettings
{
bool IsDirty { get; }
bool SaveSettings();
bool LoadSettings();
}

public partial class UserControl1 : UserControl, ISettings
{
private bool isdirty;
public bool IsDirty
{
get { return (isdirty);}
set { isdirty = value;}
}

//Commits all changes for all tabs to the database, true if success,
false if failure
public bool SaveSettings()
{
bool bRet = false;

return (bRet);
}

//Commits all changes for all tabs to the database, true if success,
false if failure
public bool LoadSettings()
{
bool bRet = true;

return (bRet);
}

public UserControl1()
{
InitializeComponent();
}
}



public delegate bool CustomSaveHandler();

public partial class Form1 : Form
{

public Form1()
{
InitializeComponent();
LoadConfigurationUserControls();

}

private void LoadConfigurationUserControls()
{
bool bClass = false;

CustomSaveHandler a = null;
List<stringlist = new List<string>();
try
{
Assembly asm = Assembly.LoadFrom(@"C:\Mydll.dll");
// Walk through each type in the assembly looking for our
class
foreach (Type type in asm.GetTypes())
{
if (type.IsClass == true )
{
bClass = false;
foreach (Type interfaceType in type.GetInterfaces())
{
if (interfaceType.FullName.Contains("ISettings"))
{
bClass = true;
break;
}
}

if(bClass)
{
Control control = Activator.CreateInstance(type)
as Control;
xtraTabControl1.TabPages.Add();

xtraTabControl1.TabPages[xtraTabControl1.TabPages.Count - 1].Text =
type.FullName;

xtraTabControl1.TabPages[xtraTabControl1.TabPages.Count-1].Controls.Add(control);

MethodInfo typemethod =
type.GetMethod("SaveSettings");

a +=
(CustomSaveHandler)Delegate.CreateDelegate(typeof( CustomSaveHandler),
typemethod);

}
}
}


"Jon Skeet [C# MVP]" wrote:
On Sep 5, 3:51 pm, sippyuconn <sippyuc...@newsgroup.nospamwrote:
Sorry one more ??

I get an exception
Error binding to target method.

That can happen for a number of reasons. Post a short but complete
program and we can try to work out why.
See http://pobox.com/~skeet/csharp/complete.html for more details.

Jon
Sep 6 '08 #18
On Fri, 05 Sep 2008 18:02:01 -0700, sippyuconn
<si********@newsgroup.nospamwrote:
Here is a complete sample [...]
I see neither a Main() method, nor an InitializeComponent() for any of
your Control subclasses (including the form itself). The code you posted
doesn't seem "complete" to me.

At the same time, Jon and I have both provided an answer that probably
would resolve your question. Have you looked at that yet?

Pete
Sep 6 '08 #19

"raylopez99" <ra********@yahoo.comwrote in message
news:d5**********************************@c65g2000 hsa.googlegroups.com...
On Sep 5, 2:54 am, "Pavel Minaev" <int...@gmail.comwrote:
Thanks, that was interesting. From Jon's link I see that the tool at
RedGate assumes you do not use the 'obfuscator', otherwise, they would
not mention it (see %%% below).
Well yes. The point of obfuscators is to make decompiled code unreadable.
Note that you can still decompile the code, and you can still reference the
obfuscated .exe/.dll and call the public methods within, though. Obfuscators
will typically mangle internal & private member identifiers within the
assembly so that they are unreadable, and rearrange IL so that tools like
Reflector will have a hard time to tell that something is a for-loop, for
example, and will instead decompile to a mess of if-else-goto. But
technically, even such obfuscated decompiled code fully captures the logic
of the algorithm, it's just very hard to read.
From this I conclude that when in non-release, non-obfuscated code,
your .exe file is like a .dll file for .NET assemblies--I did not know
that.
Debug/Release is absolutely irrelevant here - it only concerns IL
optimizations. An assembly is still an assembly in either of those modes.
Regarding obfuscation, see above.
Sep 6 '08 #20
On Sep 5, 2:54 am, "Pavel Minaev" <int...@gmail.comwrote:
Well yes. The point of obfuscators is to make decompiled code unreadable.
Note that you can still decompile the code, and you can still reference the
obfuscated .exe/.dll and call the public methods within, though.
But technically, even such obfuscated decompiled code fully captures the logic
of the algorithm, it's just very hard to read.
Well that's interesting. So you are saying a Reflector can still call
on the public methods of obfuscated code--it's the internal structure
of the methods that is scrambled. Very interesting.

RL

Sep 6 '08 #21
raylopez99 wrote:
>On Sep 5, 2:54 am, "Pavel Minaev" <int...@gmail.comwrote:
Well yes. The point of obfuscators is to make decompiled code unreadable.
Note that you can still decompile the code, and you can still reference the
obfuscated .exe/.dll and call the public methods within, though.
>But technically, even such obfuscated decompiled code fully captures the logic
of the algorithm, it's just very hard to read.

Well that's interesting. So you are saying a Reflector can still call
on the public methods of obfuscated code--it's the internal structure
of the methods that is scrambled. Very interesting.
You may benefit from reading:
http://www.excelsior-usa.com/article...fuscators.html

(it is about Java, but you can more or less replace all occurrences
of "Java" with "C#")

Arne
Sep 6 '08 #22
On Sep 6, 2:34*pm, Arne Vajhøj <a...@vajhoej.dkwrote:
>
You may benefit from reading:
* *http://www.excelsior-usa.com/article...fuscators.html

(it is about Java, but you can more or less replace all occurrences
of "Java" with "C#")

Thanks. I read it, and don't believe it. I find this particularly
hard to believe:

/*
Impact of Flow Obfuscation on Performance

You may now wonder what might be the degree of impact of such
extensive transformations on application performance. So did I,
therefore my next step was running a well-known benchmark suite
through JBCO.

The slowdown ranges from 3.3x for the Monte Carlo test to over 30x for
SOR and LU. The composite score is 22.8x lower for the obfuscated
version!
*/

I can't believe an obfuscator, which is simply affecting the human
readable source code and should not affect the machine code, would
slowdown something even 3%, much less 3.3x to 30x. Something's not
right.

RL
Sep 7 '08 #23

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

3 posts views Thread by Matias Szulman | last post: by
9 posts views Thread by Christopher Weaver | last post: by
reply views Thread by zeng.hui.stephen | last post: by
2 posts views Thread by markliam | last post: by
1 post views Thread by Blip | 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.