Factory class using generics, but without a base class

I got what, in my opinion, could be an unusual problem (Ive searched a lot for an answer, but I don't think I found it).

I have messages that are read from the queue, and depending on the type of message it contains a payload that needs to be deserialized into a specific C # class. This ultimately needs to be specific (I can't use generics all the way), because Im uses expression trees to perform evaluations for classes that come from the queue.

The base class is as follows:

public abstract class BaseRuleMessage<T>  
{
    public abstract Func<T, bool> CompileRule(Rule r, T msg);

    public T Deserialize(ClientEventQueueMessage message)
    {
        return JsonConvert.DeserializeObject<T>(message.Payload);
    }        

    public BaseRuleMessage()
    {
        RulesCompleted = new List<int>();
    }

    public IEnumerable<Rule> FilterRules(RuleGroup ruleGroup)
    {
        return ruleGroup.Rules.Where(item =>
            !RulesCompleted.Any(r => r.Equals(item.Id)));
    }

I implement the base class as follows:

 public class UiTransactionUpdate : BaseRuleMessage<UiTransactionUpdate>
{

    public override Func<UiTransactionUpdate, bool> CompileRule(Rule r, UiTransactionUpdate msg)
    {
        var expression = Expression.Parameter(typeof(UiTransactionUpdate));
        Expression expr = BuildExpr(r, expression, msg);
        return Expression.Lambda<Func<UiTransactionUpdate, bool>>(expr, expression).Compile();
    }
    public Guid TransactionId { get; set; }

    public Guid GroupId { get; set; }

    public decimal StatusValue { get; set; }

Then I do something like this:

 switch (message.MessageType)
            {
                case "UI_UPDATE":
                {
                    message.Payload = RemoveNullGroupIdReference(jsonPayload, message.Payload);
                    var deserializedMessage = new UiTransactionUpdate().Deserialize(message);
                    deserializedMessage.RulesCompleted = deserializedMessage.RulesCompleted ?? new List<int>();

                    foreach (var rule in deserializedMessage.FilterRules(ruleGroup))
                    {

, factory ( ?), , .

+4
1

dynamic, , object. dynamic, .

, Func<T, bool> , Func. . , Func .

, .

// Horrible name, do change it to something more appropriate
public abstract class BaseBaseRuleMessage
{
    public IList<int> RulesCompleted { get; set; }

    public IEnumerable<Rule> FilterRules(RuleGroup ruleGroup)
    {
        return ruleGroup.Rules.Where(item =>
                !RulesCompleted.Any(r => r.Equals(item.Id)));
    }

    public BaseBaseRuleMessage DeserializeToBaseBaseRuleMessage(ClientEventQueueMessage message)
    {
        return (BaseBaseRuleMessage) DeserializeToType(message);
    }

    protected abstract object DeserializeToType(ClientEventQueueMessage message);

    public abstract bool ExecuteRule(Rule rule, object msg);
}

BaseRuleMessage BaseBaseRuleMessage ( .

public abstract class BaseRuleMessage<T> : BaseBaseRuleMessage
    where T : BaseRuleMessage<T>
{
    public abstract Func<T, bool> CompileRule(Rule r, T msg);

    protected override object DeserializeToType(ClientEventQueueMessage message)
    {
        return JsonConvert.DeserializeObject(message.Payload, typeof(T));
    }

    protected BaseRuleMessage()
    {
        RulesCompleted = new List<int>();
    }

    public override bool ExecuteRule(Rule rule, object msg)
    {
        var message = (T) msg;
        if (message == null)
        {
            throw new InvalidOperationException();
        }
        return CompileRule(rule, message).Invoke(message);
    }
}

. BuildExpr, , .

public class UiTransactionUpdate : BaseRuleMessage<UiTransactionUpdate>
{
    public override Func<UiTransactionUpdate, bool> CompileRule(Rule r, UiTransactionUpdate msg)
    {
        var expression = Expression.Parameter(typeof(UiTransactionUpdate));
        Expression expr = BuildExpr(r, expression, msg);
        return Expression.Lambda<Func<UiTransactionUpdate, bool>>(expr, expression).Compile();
    }

    public Guid TransactionId { get; set; }

    public Guid GroupId { get; set; }

    public decimal StatusValue { get; set; }

    private Expression BuildExpr(Rule rule, ParameterExpression parameterExpression, UiTransactionUpdate message)
    {
        var transactionIdProperty = Expression.Property(parameterExpression, "TransactionId");
        var value = Expression.Constant(rule.TransactionId);

        return Expression.Equal(transactionIdProperty, value);
    }
}

:

var messageTypeToTypeMap = new Dictionary<string, Func<BaseBaseRuleMessage>>
{
    {"UI_UPDATE", () => new UiTransactionUpdate()}
};

var factoryFunc = messageTypeToTypeMap[message.MessageType];
message.Payload = RemoveNullGroupIdReference(jsonPayload, message.Payload);
var ruleMessage = factoryFunc.Invoke();
var deserializedMessage = ruleMessage.DeserializeToBaseBaseRuleMessage(message);
deserializedMessage.RulesCompleted = deserializedMessage.RulesCompleted ?? new List<int>();

foreach (var rule in deserializedMessage.FilterRules(ruleGroup))
{
    var isTrue = deserializedMessage.ExecuteRule(rule, deserializedMessage);
}
+2

Source: https://habr.com/ru/post/1657274/


All Articles