Reflection改善の提案
Akeit0 opened this issue · 2 comments
Akeit0 commented
ReflectionUtil.cs ではターゲットのオブジェクトに対してキャッシュしていますが、型に対してキャッシュする方がよいと思います。
private static Dictionary<(Type, string), Func<object,object>> cacheGetter;
if (cacheGetter.TryGetValue((type, name),out var f)){
return f(target);
}
public static Func<object, object> CreateGetter(FieldInfo fieldInfo) {
if (fieldInfo.IsStatic) {
Expression body = Expression.Convert(Expression.MakeMemberAccess(null, fieldInfo), typeof(object));
var lambda = Expression.Lambda<Func<object>>(body).Compile();
return _=>lambda();
}
if (fieldInfo.DeclaringType != null) {
var objParam = Expression.Parameter(typeof(object), "obj");
var tParam= Expression.Convert(objParam, fieldInfo.DeclaringType);
Expression body = Expression.Convert(Expression.MakeMemberAccess(tParam, fieldInfo), typeof(object));
return Expression.Lambda<Func<object, object>>(body,objParam).Compile();
}
return null;
}
public static Func<object, object> CreateGetter(PropertyInfo propertyInfo) {
if (propertyInfo.GetGetMethod(true).IsStatic) {
Expression body = Expression.Convert(Expression.MakeMemberAccess(null, propertyInfo), typeof(object));
var lambda = Expression.Lambda<Func<object>>(body).Compile();
return _=>lambda();
}
if (propertyInfo.DeclaringType != null) {
var objParam = Expression.Parameter(typeof(object), "obj");
var tParam= Expression.Convert(objParam, propertyInfo.DeclaringType);
Expression body = Expression.Convert(Expression.MakeMemberAccess(tParam, propertyInfo), typeof(object));
return Expression.Lambda<Func<object, object>>(body,objParam).Compile();
}
return null;
}
AnnulusGames commented
いただいたコードを参考にReflectionUtilのコードを修正しました。ありがとうございます!
Akeit0 commented
if (!cacheGetPropertyValue.ContainsKey((type, name)))
{
//キャッシュ作る
}
if (cacheGetPropertyValue[(type, name)] == null) return null;
else return cacheGetPropertyValue[(type, name)].Invoke(target);
と書くと何回も検索していて無駄なので、
if (!cacheGetPropertyValue.TryGetValue((type, name), out var f )){
PropertyInfo info = type.GetProperty(name, bindingAttr);
cacheGetPropertyValue.Add((type, name),f=CreateGetter(info) );
}
return f?.Invoke(target)
と書くとスマートかつ検索が一回になります(正直ほかのエディタ処理の重さからしたら誤差)。out は外側で定義したものと同じ扱いなのでこう書けます。
またnull条件演算子はgetterがnullだったらnullを返してくれるので、おすすめです。
こんな書き方があるんだな程度で時間あるときに対応してみてください。