Dynamically calling methods corresponding a parameter's type using expression trees in c#

后端 未结 2 1158
暖寄归人
暖寄归人 2021-01-24 02:09

I\'m building an event handler which will work similarly to how aggregates behave in event sourced systems.

What I\'m trying to achieve can be done in ways as documented

2条回答
  •  野性不改
    2021-01-24 02:38

    You can treat lambda functions like a regular static methods. This mean you should pass additional parameter to it (Aggregate in your case). In other words you need to create lambda, that type looks like Action.

    Change declaration of your _handlers to

    private readonly IDictionary> _handlers
      = new Dictionary>();
    

    Now you can write AggregateBase constructor like this:

    var methods = this.GetType().GetMethods()
        .Where(p => p.Name == handleMethodName
                    && p.GetParameters().Length == 1);
    
    var runnerParameter = Expression.Parameter(typeof(AggregateBase), "r");
    var commonEventParameter = Expression.Parameter(typeof(Event), "e");
    
    foreach (var method in methods)
    {
        var eventType = method.GetParameters().Single().ParameterType;
    
        var body = Expression.Call(
            Expression.Convert(runnerParameter, GetType()),
            method,
            Expression.Convert(commonEventParameter, eventType)
          );
    
        var lambda = Expression.Lambda>(
          body, runnerParameter, commonEventParameter);
    
        _handlers.Add(eventType, lambda.Compile());
    }
    

    EDIT: Also you need to change invocation in Apply method:

    public void Apply(Event @event)
    {
        var type = @event.GetType();
        if (_handlers.ContainsKey(type))
            _handlers[type](this, @event);
    }
    

提交回复
热议问题