Sic.Framework-Nanjing-Baishi/MECF.Framework.RT.Equipment.../Core/Extensions/BitTypeClassExtension.cs

128 lines
4.6 KiB
C#
Raw Normal View History

2023-04-13 11:51:03 +08:00
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using MECF.Framework.RT.EquipmentLibrary.Core.Attributes;
namespace MECF.Framework.RT.EquipmentLibrary.Core.Extensions
{
public static class BitTypeClassExtension
{
/// <summary>
/// 返回类型中以<see cref="BitTypeClassPropertyAttribute"/>标记的公共属性。
/// </summary>
/// <param name="type"></param>
/// <returns></returns>
private static List<PropertyInfo> GetProperties(IReflect type)
{
var piList = type
.GetProperties(BindingFlags.Public | BindingFlags.Instance)
.Where(x => x.PropertyType == typeof(bool) &&
x.GetCustomAttributes(true)
.OfType<BitTypeClassPropertyAttribute>()
.Any());
return piList.ToList();
}
/// <summary>
/// 将整数转换为包含Bit定义的类。
/// <para>注意:</para>
/// <para>目标类中和输入整数bit对应的属性需要用<see cref="BitTypeClassPropertyAttribute"/>标记。</para>
/// </summary>
/// <typeparam name="T">包含Bit属性定义的类的类型。</typeparam>
/// <param name="bitValueSource">待转换的整数。</param>
/// <param name="bitLen">有效的位长度。</param>
/// <returns></returns>
public static T ToBitTypeClass<T>(this int bitValueSource, int bitLen)
where T : new()
{
var obj = new T();
for (var i = 0; i < bitLen; i++)
{
var pi = typeof(T)
.GetProperties(BindingFlags.Public | BindingFlags.Instance)
.FirstOrDefault(x => x.PropertyType == typeof(bool) &&
x.GetCustomAttributes(true)
.OfType<BitTypeClassPropertyAttribute>()
.Any(a => a.BitIndex == i));
if (pi != null)
{
pi.SetValue(obj, (bitValueSource & (1 << i)) != 0 ? true : false);
}
}
return (T)obj;
}
/// <summary>
/// 将BitType对象中以<see cref="BidArgumentTypeAttribute"/>标记的属性合并整理为int。
/// </summary>
/// <typeparam name="T">包含Bit属性定义的类的类型。</typeparam>
/// <param name="obj">对象实例。</param>
/// <returns></returns>
public static int FromBitTypeClass<T>(this T obj)
{
var piList = GetProperties(typeof(T));
if (!piList.Any())
return -1;
var integValue = 0;
foreach (var pi in piList)
{
// 如果该属性没有用BitTypeClassPropertyAttribute标记则忽略
if (!(pi.GetCustomAttribute(typeof(BitTypeClassPropertyAttribute)) is BitTypeClassPropertyAttribute
attr))
continue;
// 如果该属性的返回值不是bool型则忽略
if (!(pi.GetValue(obj) is bool v))
continue;
// 如果该属性为True则将返回整数的指定Bit设置为1.
if(v)
integValue |= (1 << attr.BitIndex);
}
return integValue;
}
/// <summary>
/// 从BitType类聚合错误信息。
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="obj"></param>
/// <returns></returns>
public static List<string> AggregateErrorMessages<T>(this T obj)
{
var piList = GetProperties(typeof(T));
var piForError = piList.Where(pi =>
pi.GetCustomAttributes()
.OfType<BitTypeClassPropertyAttribute>()
.Any(a => a.IsErrorBit))
.ToList();
var errs = new List<string>();
foreach (var pi in piForError)
{
if (!(pi.GetValue(obj) is bool vv))
continue;
if (!vv)
continue;
var attr = pi.GetCustomAttribute(
typeof(BitTypeClassPropertyAttribute)) as BitTypeClassPropertyAttribute;
errs.Add(attr?.Message??$"Cannot get message from {nameof(BitTypeClassPropertyAttribute)} of property {pi.Name} of object {obj}");
}
return errs;
}
}
}