forked from mini-software/MiniExcel
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request !11 from 若汝棋茗/master
- Loading branch information
Showing
6 changed files
with
259 additions
and
14 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using System.Text; | ||
using System.Threading.Tasks; | ||
|
||
namespace MiniExcelLibs | ||
{ | ||
/// <summary> | ||
/// 用于表达式树的成员 | ||
/// </summary> | ||
public abstract class Member | ||
{ | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
using System; | ||
using System.Linq.Expressions; | ||
using System.Reflection; | ||
|
||
namespace MiniExcelLibs | ||
{ | ||
/// <summary> | ||
/// 表示属性的Getter | ||
/// </summary> | ||
public class MemberGetter | ||
{ | ||
/// <summary> | ||
/// get方法委托 | ||
/// </summary> | ||
private readonly Func<object, object> m_getFunc; | ||
|
||
/// <summary> | ||
/// 表示属性的Getter | ||
/// </summary> | ||
/// <param name="property">属性</param> | ||
/// <exception cref="ArgumentNullException"></exception> | ||
public MemberGetter(PropertyInfo property) | ||
{ | ||
m_getFunc = CreateGetterDelegate(property); | ||
} | ||
|
||
/// <summary> | ||
/// 表示类型字段或属性的Getter | ||
/// </summary> | ||
/// <exception cref="ArgumentNullException"></exception> | ||
public MemberGetter(FieldInfo fieldInfo) | ||
{ | ||
m_getFunc = CreateGetterDelegate(fieldInfo); | ||
} | ||
|
||
/// <summary> | ||
/// 获取属性的值 | ||
/// </summary> | ||
/// <param name="instance">实例</param> | ||
/// <returns></returns> | ||
public object Invoke(object instance) | ||
{ | ||
return m_getFunc.Invoke(instance); | ||
} | ||
|
||
private static Func<object, object> CreateGetterDelegate(PropertyInfo property) | ||
{ | ||
var param_instance = Expression.Parameter(typeof(object)); | ||
var body_instance = Expression.Convert(param_instance, property.DeclaringType); | ||
var body_property = Expression.Property(body_instance, property); | ||
var body_return = Expression.Convert(body_property, typeof(object)); | ||
|
||
return Expression.Lambda<Func<object, object>>(body_return, param_instance).Compile(); | ||
} | ||
|
||
private static Func<object, object> CreateGetterDelegate(FieldInfo fieldInfo) | ||
{ | ||
var param_instance = Expression.Parameter(typeof(object)); | ||
var body_instance = Expression.Convert(param_instance, fieldInfo.DeclaringType); | ||
var body_field = Expression.Field(body_instance, fieldInfo); | ||
var body_return = Expression.Convert(body_field, typeof(object)); | ||
|
||
return Expression.Lambda<Func<object, object>>(body_return, param_instance).Compile(); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
using System; | ||
using System.Linq.Expressions; | ||
using System.Reflection; | ||
|
||
namespace MiniExcelLibs | ||
{ | ||
/// <summary> | ||
/// 表示属性的设置器 | ||
/// </summary> | ||
public class MemberSetter | ||
{ | ||
/// <summary> | ||
/// set方法委托 | ||
/// </summary> | ||
private readonly Action<object, object> setFunc; | ||
|
||
/// <summary> | ||
/// 表示属性的Getter | ||
/// </summary> | ||
/// <param name="property">属性</param> | ||
/// <exception cref="ArgumentNullException"></exception> | ||
public MemberSetter(PropertyInfo property) | ||
{ | ||
if (property == null) | ||
{ | ||
throw new ArgumentNullException(nameof(property)); | ||
} | ||
setFunc = CreateSetterDelegate(property); | ||
} | ||
|
||
/// <summary> | ||
/// 设置属性的值 | ||
/// </summary> | ||
/// <param name="instance">实例</param> | ||
/// <param name="value">值</param> | ||
/// <returns></returns> | ||
public void Invoke(object instance, object value) | ||
{ | ||
setFunc.Invoke(instance, value); | ||
} | ||
|
||
private static Action<object, object> CreateSetterDelegate(PropertyInfo property) | ||
{ | ||
var param_instance = Expression.Parameter(typeof(object)); | ||
var param_value = Expression.Parameter(typeof(object)); | ||
|
||
var body_instance = Expression.Convert(param_instance, property.DeclaringType); | ||
var body_value = Expression.Convert(param_value, property.PropertyType); | ||
var body_call = Expression.Call(body_instance, property.GetSetMethod(true), body_value); | ||
|
||
return Expression.Lambda<Action<object, object>>(body_call, param_instance, param_value).Compile(); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,110 @@ | ||
|
||
using System; | ||
using System.Collections.Concurrent; | ||
using System.Linq; | ||
using System.Reflection; | ||
|
||
namespace MiniExcelLibs | ||
{ | ||
/// <summary> | ||
/// 表示属性 | ||
/// </summary> | ||
public class Property: Member | ||
{ | ||
/// <summary> | ||
/// 类型属性的Setter缓存 | ||
/// </summary> | ||
private static readonly ConcurrentDictionary<Type, Property[]> m_cached = new ConcurrentDictionary<Type, Property[]>(); | ||
|
||
/// <summary> | ||
/// 获取器 | ||
/// </summary> | ||
private readonly MemberGetter m_geter; | ||
|
||
/// <summary> | ||
/// 设置器 | ||
/// </summary> | ||
private readonly MemberSetter m_seter; | ||
|
||
/// <summary> | ||
/// 属性 | ||
/// </summary> | ||
/// <param name="property">属性信息</param> | ||
public Property(PropertyInfo property) | ||
{ | ||
Name = property.Name; | ||
Info = property; | ||
|
||
if (property.CanRead == true) | ||
{ | ||
CanRead = true; | ||
m_geter = new MemberGetter(property); | ||
} | ||
if (property.CanWrite == true) | ||
{ | ||
CanWrite = true; | ||
m_seter = new MemberSetter(property); | ||
} | ||
} | ||
|
||
/// <summary> | ||
/// 是否可以读取 | ||
/// </summary> | ||
public bool CanRead { get; private set; } | ||
|
||
/// <summary> | ||
/// 是否可以写入 | ||
/// </summary> | ||
public bool CanWrite { get; private set; } | ||
|
||
/// <summary> | ||
/// 获取属性信息 | ||
/// </summary> | ||
public PropertyInfo Info { get; private set; } | ||
|
||
/// <summary> | ||
/// 获取属性名称 | ||
/// </summary> | ||
public string Name { get; protected set; } | ||
|
||
/// <summary> | ||
/// 从类型的属性获取属性 | ||
/// </summary> | ||
/// <param name="type">类型</param> | ||
/// <returns></returns> | ||
public static Property[] GetProperties(Type type) | ||
{ | ||
return m_cached.GetOrAdd(type, t => t.GetProperties().Select(p => new Property(p)).ToArray()); | ||
} | ||
|
||
/// <summary> | ||
/// 获取属性的值 | ||
/// </summary> | ||
/// <param name="instance">实例</param> | ||
/// <exception cref="NotSupportedException"></exception> | ||
/// <returns></returns> | ||
public object GetValue(object instance) | ||
{ | ||
if (m_geter == null) | ||
{ | ||
throw new NotSupportedException(); | ||
} | ||
return m_geter.Invoke(instance); | ||
} | ||
|
||
/// <summary> | ||
/// 设置属性的值 | ||
/// </summary> | ||
/// <param name="instance">实例</param> | ||
/// <param name="value">值</param> | ||
/// <exception cref="NotSupportedException"></exception> | ||
public void SetValue(object instance, object value) | ||
{ | ||
if (m_seter == null) | ||
{ | ||
throw new NotSupportedException($"{Name}不允许赋值"); | ||
} | ||
m_seter.Invoke(instance, value); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters