I'm dynamically loading an assembly, creating an instance of a class that implements IRegisterable
, then calling a registration method with this shortened code:
public bool RegisterASM(string path)
{
Assembly asm = LoadAssembly(path); //helper to load assembly
if (asm != null)
{
var registerableTypes = from t in asm.GetTypes()
where t.IsClass &&
(t.GetInterface("IRegisterable") != null)
select t;
foreach (Type t in registerableTypes)
{
IRegisterable reg = (IRegisterable)asm.CreateInstance(t.FullName, true);
reg.Register(this);
}
return true;
}
else
{
Console.WriteLine("Assembly not found");
return false;
}
}
And an example of the IRegisterable
class:
public class Class1 : IRegisterable
{
public bool Register(IRegistrationUtilities regHandler)
{
Action<Dictionary<string, object>> actionMeathod = TestJob;
regHandler.RegisterJob(actionMeathod, "Testing", 30000, true);
Class3 c = new Class3();
actionMeathod = c.TestJob3;
regHandler.RegisterJob(actionMeathod, "Test3", 5000, true);
return true;
}
public void TestJob(Dictionary<string, object> vars)
{
Console.WriteLine("SleepStart");
Thread.Sleep(40000);
Console.WriteLine("SleepEnd");
}
}
public class Class3
{
int t = 5;
public void TestJob3(Dictionary<string, object> vars)
{
Console.WriteLine("test 3...{0}", t);
}
}
When the class registers, it calls a method in the RegistrationHandler
that will in turn call a method in the JobScheduler
that will create a Threading.Timer
with the TimerCallback
being the actionMeathod
passed in the registration. Besides that, there is no other reference to the IRegisterable
class.
My question is, does the class stay in memory since there is a reference to the method or is the class recreated every time the method is called? Or a combination of both?
The reason I ask is that Class1.Register
creates an instance of Class3
and passes Class3.TestJob3
as the actionMeathod
. When Class3
is created, it sets t=5
, which is used in TestJob3
. but when the Register
method exits, the instance of Class3
is destroyed since it was a local variable. But the timed call to Class3.TestJob3
still has t=5
, so is Class3
recreated every time or does it persist?
but when the
Register
method exits, the instance ofClass3
is destroyed since it was a local variable.
This is incorrect for reference types. Reference objects are allocated on the heap. The local variable c
merely points to this object. The garbage collector will destroy the instance at a later time when it determines that the object is not referenced.
However, the delegate object (Action<Dictionary<string, object>>
) has a reference to the Class3
object, so it will not be garbage collected until that delegate object itself can be collected. So the Class3
instance will indeed outlive execution of the Register()
method, since it will still be referenced by the delegate after this method returns.
You can prove this to yourself:
Class3 c = new Class3();
actionMeathod = c.TestJob3;
regHandler.RegisterJob(actionMeathod, "Test3", 5000, true);
// Add this line.
Console.WriteLine(object.ReferenceEquals(c, actionMeathod.Target));
The output will be "True", indicating that the delegate does indeed have a reference to the same object that c
does.