Click here to Skip to main content
15,887,824 members
Please Sign up or sign in to vote.
1.00/5 (1 vote)
See more:
Hi,
Suppose I have created a dll that have an static class and have an static event like
DLL project:
C#
public static class TestApplication
    {


          public static event TestStateHandler AfterTestComplete;
          public static void Startup();

    }


Main Project that use DLL.
Now I want to bind a method of my main project Program.cs file.I am able to call Startup() method,but how to bind program.cs method to AfterTestComplete event.
I am using this approch
Assembly DLL = Assembly.LoadFile(Path.Combine(System.AppDomain.CurrentDomain.BaseDirectory, "Refdll", "Tests.dll"));
                 //Get Test
                Type Test = DLL.GetType("Test");
               
                //Type dd=DLL.GetType("Fiddler.SessionStateHandler");

                MethodInfo IsStarted = Test.GetMethod("Startup");
                EventInfo AfterTestComplete;
                if (!Convert.ToBoolean(IsStarted.Invoke(null, null)))
                {

                    AfterTestComplete = Test.GetEvent("AfterSessionComplete");
                    Type delegateType = AfterTestComplete.EventHandlerType;
                    MethodInfo mm = AfterTestComplete.AddMethod;


Now how to bind a method of program.cs to AfterTestComplete event.
Posted
Comments
Andy Lanng 13-Jul-15 6:49am    
Ok - this is fairly simple. Just to clarify:
You want to call a method from a loaded assembly in the AfterTextCompete event. Correct?

Oh I see. You want to call a local scope method when the loaded assembly event fires. Gotcha.

Question: How does the event fire? Are you instantiating the loaded assembly?
uspatel 13-Jul-15 8:41am    
Yes,there is a delegate,TestStateHandler
Andy Lanng 13-Jul-15 10:27am    
I think you misunderstood my question. let me rephrase:

In order to fire the event, a class method in the loaded assembly must be running. This means that you need to call the constructor, or run a method if it's a static class.

The alternative is to trigger the event locally but then you should load just a handler in this way.

My question was: How are you triggering the event in the loaded assembly?

The way you use a loaded assembly is to safe-cast it to a known type or delegate:
TestStateHandler handler = AfterTestComplete as TestStateHandler;

If it can't safe-cast then handler==null.

1 solution

I don't know why you want to use the assembly (assembly, not "DLL") loaded during runtime, but you may have your reasons.

You are doing it in a bad way from the very beginning. Look at your code using reflection. It relies on hard-coded magic words the strings "Test", "Startup", "AfterSessionComplete", and the like. This is unsupportable and extremely unreliable. The compiler won't warn you if you misspell any of these magic words, and what if you decide to change some of the names? So, this is rubbish which belongs to a dumpster.

The reflection problem without hard-coding can be simply resolved. For example, you could create some interface known to both host application assembly and the plug-in assembly. It could be declared in some library assembly, but you can even declare it in your host application assembly. The plug-in assembly can statically reference the host application assembly (yes, despite of one of the common misconception "EXE" assembly can also be referenced; in .NET, distinction between "EXE" and "DLL" is not essential). It would not create any circular dependencies.

You can always use some event declaration in your interface. Only TestStateHandler type is not so good. The mainstream way of defining event instance type is this: first define event arguments type derived from System.EventArgs and then use it in generic System.EventHandler:
C#
public class MyEventArgs : System.EventArgs {/* ... */}

public interface IMyPlugin {
   public static event System.EventHandler<MyEventArgs> AfterTestComplete;
   // ...
}
But, in principle, you can use your TestStateHandler, if you really want it, but I don't see why…

Now what? In the host application, you need to find some type which implements this interface. How? This is the simplest way: https://msdn.microsoft.com/en-us/library/system.type.isassignablefrom%28v=vs.110%29.aspx[^].

If more than one type implements this interface, do… whatever you want, say, use the first one, or deny the whole assembly as wrong one. I go further and define a special assembly-level attribute which claims that certain type(s) implement certain plug-in interface(s), and then I don't have to traverse all the type, but have to check up this claim during runtime. You can find further detail in my past answers:
Access a custom object that resides in plug in dll[^],
Gathering types from assemblies by it's string representation[^],
C# Reflection InvokeMember on existing instance[^],
Dynamically Load User Controls[^].

At the end of your reflection work, you instantiate the desired class which, as you found, implements the interface you want. For instantiation, you either use Activator.CreateInstance(Type), or use MethodInfo.Invoke on a constructor. So, you can safely type-cast the type reference to the interface reference:
C#
IMyPlugin plugin = (IMyPlugin)instantiatedType;

From this point, you can use the object reference plugin to add your event handler to the invocation list of the event instance in question, or do whatever else you need to do with this object, as you would do with any instance of any statically known type.

—SA
 
Share this answer
 
v4
Comments
Wendelius 13-Jul-15 13:02pm    
Well explained
Sergey Alexandrovich Kryukov 13-Jul-15 13:30pm    
Thank you, Mika.
—SA

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900