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
{
///
/// 返回类型中以标记的公共属性。
///
///
///
private static List GetProperties(IReflect type)
{
var piList = type
.GetProperties(BindingFlags.Public | BindingFlags.Instance)
.Where(x => x.PropertyType == typeof(bool) &&
x.GetCustomAttributes(true)
.OfType()
.Any());
return piList.ToList();
}
///
/// 将整数转换为包含Bit定义的类。
/// 注意:
/// 目标类中和输入整数bit对应的属性需要用标记。
///
/// 包含Bit属性定义的类的类型。
/// 待转换的整数。
/// 有效的位长度。
///
public static T ToBitTypeClass(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()
.Any(a => a.BitIndex == i));
if (pi != null)
{
pi.SetValue(obj, (bitValueSource & (1 << i)) != 0 ? true : false);
}
}
return (T)obj;
}
///
/// 将BitType对象中以标记的属性合并整理为int。
///
/// 包含Bit属性定义的类的类型。
/// 对象实例。
///
public static int FromBitTypeClass(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;
}
///
/// 从BitType类聚合错误信息。
///
///
///
///
public static List AggregateErrorMessages(this T obj)
{
var piList = GetProperties(typeof(T));
var piForError = piList.Where(pi =>
pi.GetCustomAttributes()
.OfType()
.Any(a => a.IsErrorBit))
.ToList();
var errs = new List();
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;
}
}
}