I am trying to determine what issues could be caused by using the following serialization surrogate to enable serialization of anonymous functions/delegate/lambdas.
A function map would prevent me from using local state in the action/conditions. The only way around this would work would be to create a class per function that required additional state.
This is what the C# compiler is doing automatically for me with anonymous functions. My issue is the serialization of these compiler classes.
Other o = FromSomeWhere();
Thing t = OtherPlace();
target.OnWhatever = () => t.DoFoo() + o.DoBar();
target.Save();c
Trying to serialize that would fail. Since this state is local though that leads to issues when trying to setup a mapping. Instead I'd have to declare something like this:
[Serializable]
abstract class Command<T>
{
public abstract T Run();
}
class DoFooBar : Command<int>
{
public Other Other { get; set; }
public Thing Thing { get; set; }
public override int Run()
{
return Thing.DoFoo() + Other.DoBar();
}
}
and then use it like this:
DoFooBar cmd = new DoFooBar();
cmd.Other = FromSomewhere();
cmd.Thing = OtherPlace();
target.OnWhatever = cmd.Run;
target.Save();
Essentially what this means is doing manually what the C# compiler is doing for me automatically.
Did you see this post that I wrote as a followup to the CountingDemo: http://dotnet.agilekiwi.com/blog/2007/12/update-on-persistent-iterators.html ? Unfortunately, Microsoft have confirmed that they probably will change the compiler details (one day), in a way that is likely to cause problems. (e.g. f/when you update to the new compiler, you won't be able to deserialise the stuff you saved under the old (current) compiler.)
I'm not 100% on this, but I believe that if you want to "save" a delegate or some code to the database that can be fairly dynamic, what you need to do is create an Expression, then you can compile the expression into a Func<...>.
Expression Tree Basics
Late Bound Invocations with Expression Trees
Some objects need execute arbitrary "events" reaching some condition.
Just how arbitrary are these events? Can they be counted, assigned ID's and mapped to referentially?
public class Command<T> where T : ISerializable
{
T _target;
int _actionId;
int _conditionId;
public Command<T>(T Target, int ActionId, int ConditionId)
{
_target = Target;
_actionId = ActionId;
_conditionId = ConditionId;
}
public bool FireRule()
{
Func<T, bool> theCondition = conditionMap.LookupCondition<T>(_conditionId)
Action<T> theAction = actionMap.LookupAction<T>(_actionId);
if (theCondition(_target))
{
theAction(_target);
return true;
}
return false;
}
}
Since this state is local though that leads to issues when trying to setup a mapping.
Wouldn't local state present the exact same problems for serialization?
Suppose the compiler and the framework allowed this to work:
Other o = FromSomeWhere();
Thing t = OtherPlace();
target.OnWhatever = () => t.DoFoo() + o.DoBar();
target.Save();
I guess t and o had to be serialized too. The methods don't have the state, the instances do.
Later, you deserialize target. Don't you get new copies of t and o? Won't these copies be out of sync with any changes to the original t and o?
Also: couldn't your manual example be called this way?
Other o = FromSomeWhere();
Thing t = OtherPlace();
target.OnWhatever = new DoFooBar() {Other = o, Thing = t} .Run;
target.Save();
The whole idea of serializing a delegate is very risky. Now, an expression might make sense, but even that is hard to express - although the dynamic-LINQ samples go some way to allowing a form of text-based expression.
What exactly is it you want to do with a serialized delegate? I really don't think this is a good idea...