gpt4 book ai didi

c# - 使用泛型但没有基类的工厂类

转载 作者:太空狗 更新时间:2023-10-29 23:36:56 25 4
gpt4 key购买 nike

我遇到了我认为可能是一个不寻常的问题(我已经搜索了很多答案,但我认为我没有找到)。

我有从队列中读取的消息,并且根据消息类型包含需要反序列化为具体 C# 类的负载。这需要最终是具体的(我不能一直使用泛型),因为我使用表达式树对从队列中到达的类执行评估。

基类如下所示:

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)));
}

我这样实现基类:

 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; }

然后我做这样的事情来调用:

 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))
{

我真正想知道的是我如何创建一个工厂(或者我可以吗?)以能够返回一个具体类用于我的表达式树的方式定义基类的实现评估而不必为每种类型重复所有调用代码。

最佳答案

我避免使用 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);
}

更新了 BaseRuleMessageBaseBaseRuleMessage 派生(并将一些属性移至基类。

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);
}

关于c# - 使用泛型但没有基类的工厂类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39959294/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com