首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >基于电气工程公式输入和条件标准c#的返回枚举结果通用类

基于电气工程公式输入和条件标准c#的返回枚举结果通用类
EN

Stack Overflow用户
提问于 2020-06-06 16:19:22
回答 3查看 76关注 0票数 1

我从事一个需要进行工程公式检查/验证的程序。非常类似于单元测试,但我需要一些非常通用的东西,所以我不需要做大量的类。

I需要传递一个输入公式:示例:x=输入电压,y=电压参考,以求分贝。方程为20*log10 10(x/y)

并验证用例应用程序的结果。

例句:如果应用程序不能超过60分贝,值为72,则结果失败。

我有这么多这样的工作要做,所以最好有一个泛型类,将输入公式作为Func<>传入,然后有一个Dictionary (或其他什么)来返回该应用程序的结果。

以下是我的想法/需要:

非工作代码,只是为了说明概念

代码语言:javascript
复制
public enum CiteriaCheckResult
    {
        Inconclusive,
        Fail,
        Warning,
        Pass
    }

//T is the return type of the specific engineering formula
public class CriteriaCheck<T> 
        {
            public Dictionary<?, CiteriaCheckResult> Criteria { get; set; } = new Dictionary<?, CiteriaCheckResult>();

            //T1 and T2 are the inputs for a specific engineering formula
            //T is the output value to test against the criteria conditions
            public CiteriaCheckResult Validate<T1, T2>(Func<T1, T2, T> input)
            {
                //nested if's?
                //switch case?
                //Criteria.FirstOrDefault(k => k.Key == input result == criteria)?

                return CiteriaCheckResult base on dictionary or other user configurable criteria type;
            }
        }

想要的用法:

代码语言:javascript
复制
class Program
    {
        static void Main(string[] args)
        {
            var test1 = new CriteriaCheck<double>();
            //add criteria for specific application
            Criteria.Add("criteria to check against input result", CiteriaCheckResult.Inconclusive);
            Criteria.Add("value is < [] && value is > []", CiteriaCheckResult.Fail);
            Criteria.Add("value is <= Room.Value", CiteriaCheckResult.Pass);
            Criteria.Add("if value is > -6", CiteriaCheckResult.Warning);

            double x = 1.23;
            double y = .7549;

            //run func and return enum based on user set conditions
            Console.WriteLine($"Test 1: {test1.Validate<double, double>((x,y) => 20 * Math.Log10(x/y))}");



            Console.ReadKey();
        }
    }

很明显,我所展示的东西有很多问题(比如字典键没有唯一的值),但希望我想要实现的目标是明确的,你可以想出一个聪明的方法来做到这一点。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2020-06-08 18:37:21

谢谢你们的时间和精力。今天早上我发现需求发生了变化,包括验证消息,为什么需要在GUI上显示标准失败的原因。

因此,我将创建一个实现INotifyDataErrorInfo的基类,并为每个验证类型创建一个类。会有更多的类,但是泛型类不能处理所有的新需求。

示例用法

代码语言:javascript
复制
public class EquipmentRackSizeCriteriaCheck : CriteriaCheckItemBase
    {
        public override void Initialize()
        {
            //set description
            CheckProperty = "Check Equipment Enclosure Size";

            //set validation rules
            AddValidationRule<EquipmentRackSizeCriteriaCheck, double>(CiteriaCheckResult.Fail, "Equipment is too tall for the Enclosure", t => t.EquipmentRUHeight > t.EnclosureRUHeight);
            AddValidationRule<EquipmentRackSizeCriteriaCheck, double>(CiteriaCheckResult.Warning, "Enclosure is taller than the Equipment", t => t.EquipmentRUHeight < t.EnclosureRUHeight);
            AddValidationRule<EquipmentRackSizeCriteriaCheck, double>(CiteriaCheckResult.Pass, "Equipment height fits in the Enclosure", t => t.EquipmentRUHeight == t.EnclosureRUHeight);

            AddValidationRule<EquipmentRackSizeCriteriaCheck, double>(CiteriaCheckResult.Fail, "Equipment is too wide for the Enclosure", t => t.EquipmentRUWidth > t.EnclosureRUWidth);
            AddValidationRule<EquipmentRackSizeCriteriaCheck, double>(CiteriaCheckResult.Warning, "Enclosure is wider than the Equipment", t => t.EquipmentRUWidth < t.EnclosureRUWidth);
            AddValidationRule<EquipmentRackSizeCriteriaCheck, double>(CiteriaCheckResult.Pass, "Equipment width fits in the Enclosure", t => t.EquipmentRUWidth == t.EnclosureRUWidth);

            //initialize complete
            base.Initialize();
        }

        public int EquipmentRUHeight { get; set; }
        public int EquipmentRUWidth { get; set; }
        public int EnclosureRUHeight { get; set; }
        public int EnclosureRUWidth { get; set; }
    }

基类

代码语言:javascript
复制
public class CriteriaCheckItemBase : INotifyDataErrorInfo, ISupportInitializeNotification
    {
        private Dictionary<CiteriaCheckResultType, Dictionary<string, LambdaExpression>> _validationDictionary = new Dictionary<CiteriaCheckResultType, Dictionary<string, LambdaExpression>>();

        public CriteriaCheckItemBase()
        {
            //intialize object
            BeginInit();
        }

        public virtual void Initialize()
        {
            //set description
            //CheckProperty = "";

            //set validation rules

            //initialize complete
            EndInit();
        }

        public string CheckProperty { get; set; }

        public CiteriaCheckResultType CheckResult { get; set; }

        public string CheckMessage { get; set; }

        public ObservableCollection<CriteriaCheckResult> ResultsCollection { get; set; } = new ObservableCollection<CriteriaCheckResult>();

        public void AddValidationRule<T1, T2>(CiteriaCheckResultType checkResult, string message, Expression<Func<T1, bool>> rule) where T1 : CriteriaCheckItemBase
        {
            if (!_validationDictionary.ContainsKey(checkResult))
            {
                _validationDictionary.TryAdd(checkResult, new Dictionary<string, LambdaExpression>());
            }

            if (_validationDictionary.TryGetValue(checkResult, out Dictionary<string, LambdaExpression> rules))
            {
                rules.TryAdd(message ?? "No Message for this Result", rule);
            }
        }

        #region INotifyDataErrorInfo

        public bool HasErrors => (GetErrors("") is Dictionary<CiteriaCheckResultType, List<string>> c) ? c.Count > 0 : false;

        public event EventHandler<DataErrorsChangedEventArgs> ErrorsChanged;

        public IEnumerable GetErrors(string propertyName)
        {
            var results = _validationDictionary.OrderBy(o => (int)o.Key).ToDictionary(k => k.Key, v => v.Value.Where(c => (bool)c.Value.Compile().DynamicInvoke(this)).Select(s => s.Key).ToList());

            ResultsCollection.Clear();

            foreach (CiteriaCheckResultType resultType in results.Keys)
            {
                foreach (string msg in results[resultType])
                {
                    ResultsCollection.Add(new CriteriaCheckResult() { CheckResult = resultType, CheckMessage = msg });
                }
            }

            return ResultsCollection;
        }

        #endregion


        #region ISupportInitializeNotification

        public event EventHandler Initialized;

        private bool _isInitialized;
        public bool IsInitialized
        {
            get { return _isInitialized; }
            private set
            {
                _isInitialized = value;
                if (_isInitialized) { RaiseInitialized(); }
            }
        }

        public void BeginInit()
        {
            if (IsInitialized) { IsInitialized = false; }
            else { Initialize(); }
        }

        public void EndInit()
        {
            IsInitialized = true;
        }

        #endregion

        protected void RaiseInitialized()
        {
            this.Initialized?.Invoke(this, new EventArgs());
        }

        public void RaisErrorChanged([CallerMemberName] string propertyName = null)
        {
            this.ErrorsChanged?.Invoke(this, new DataErrorsChangedEventArgs(propertyName));
        }
    }
票数 0
EN

Stack Overflow用户

发布于 2020-06-06 20:31:56

以下是我的建议:

代码语言:javascript
复制
class Program
{
    static void Main(string[] args)
    {
        var checker = new CriteriaCheck<double>
        {
            FailValidator = (input => input < 0)
        };
        var result = checker.Validate((x, y) => x * y, 1.2, 0.7);
    }
}

public enum CiteriaCheckResult
{
    Inconclusive,
    Fail,
    Warning,
    Pass
}

public class CriteriaCheck<T>
{
    public Func<T, bool> InconclusiveValidator { get; set; } = p => false;
    public Func<T, bool> FailValidator { get; set; } = p => false;
    public Func<T, bool> WarningValidator { get; set; } = p => false;

    public CiteriaCheckResult Validate<T1, T2>(Func<T1, T2, T> input, T1 t1, T2 t2)
    {
        if (InconclusiveValidator(input(t1, t2)))
            return CiteriaCheckResult.Inconclusive;
        else if (FailValidator(input(t1, t2)))
            return CiteriaCheckResult.Fail;
        else if (WarningValidator(input(t1, t2)))
            return CiteriaCheckResult.Warning;
        else
            return CiteriaCheckResult.Pass;
    }
}
票数 1
EN

Stack Overflow用户

发布于 2020-06-07 19:15:40

一种可能的解决办法。我试着添加一些评论,让它变得不言自明。

代码语言:javascript
复制
public enum CiteriaCheckResult
{
    Inconclusive,
    Fail,
    Warning,
    Pass
}

//T is the return type of the specific engineering formula
public class CriteriaCheck<T>
{
    public Dictionary<Type, object[]> Criteria = new Dictionary<Type, object[]>();

    //T1 and T2 are the inputs for a specific engineering formula
    //T is the output value to test against the criteria conditions
    public CiteriaCheckResult Validate<T1, T2>(Func<T1, T2, T> input, T1 x, T2 y)
    {
        if(Criteria.Keys.Contains(input.GetType()))
        {
            // Calculate/Run the Func the value from incoming parameters
            T result = input(x, y);
            object[] m1 = Criteria[input.GetType()];

            // Calculate/Run the Func existing in the Array
            T m2 = (m1[0] as Func<T1, T2, T>)(x, y);
            if(result.Equals(m2))
            {
               // If the values match then:
                return (CiteriaCheckResult)m1[1];
            }
        }
        return CiteriaCheckResult.Inconclusive;
    }
}

class Program
{
    static void Main(string[] args)
    {
        Func<decimal, decimal, int> n1 = (x,y) => 1;
        Func<int, int> n2 = (x) => 5;
        Func<decimal, decimal, decimal> n3 = (x, y) => 3;

        CriteriaCheck<decimal> test = new CriteriaCheck<decimal>();

        object[] obj0 = { n1, CiteriaCheckResult.Fail };
        test.Criteria.Add(n1.GetType(), obj0);

        object[] obj1 = { n2, CiteriaCheckResult.Inconclusive };
        test.Criteria.Add(n2.GetType(), obj1);

        object[] obj2 = { n3, CiteriaCheckResult.Pass };
        test.Criteria.Add(n3.GetType(), obj2);

        var result = test.Validate(n3, 1, 2);
    }
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/62234567

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档