我有这些课程:
public class Entity
{
public static readonly EntitySchema Schema = new EntitySchema();
}
public abstract class BaseSchema
{
public abstract string Name {get;}
}
public class EntitySchema : BaseSchema
{
public override string Name => "Schema";
}
现在,我想从一个方法访问EntitySchema.Name
,该方法对实体一无所知(无法访问静态字段)。
我可以用反射做到这一点:
static BaseSchema GetSchema<T>()
{
var pr = typeof(T).GetField("Schema");
var schema = pr.GetValue(null);
return schema as BaseSchema;
}
但与直接通话Entity.Schema.Name
相比,反射版本慢了50倍。
有没有办法将反射版本转换为表达式树并预编译调用?
答案 0 :(得分:2)
当然可以这样做,但.NET需要具有完整的字段定义(在本例中为EntitySchema global::Entity.Schema
)才能获得实际值。反思可以为您提供此定义。您需要为每种类型创建一个委托,即:
public static class SchemaGetter
{
private static readonly Dictionary<object, Func<BaseSchema>> _lookup = new Dictionary<object, Func<BaseSchema>>();
public static BaseSchema Get<T>()
{
Func<BaseSchema> action;
if(!_lookup.TryGetValue(typeof(T), out action))
{
action = MakeDelegate<T>();
_lookup.Add(typeof(T), action);
}
return action();
}
private static Func<BaseSchema> MakeDelegate<T>()
{
// We did this before already...
FieldInfo field = typeof(T).GetField("Schema", BindingFlags.Public | BindingFlags.Static);
var fieldExpression = Expression.Field(null, field);
var lambda = Expression.Lambda<Func<BaseSchema>>(fieldExpression);
return lambda.Compile();
}
}
后面跟BaseSchema schema = SchemaGetter.Get<Entity>()
获取实际架构。
也许它足以缓存您从初始GetSchema<T>()
实现中获得的结果(将其包装在字典查找中)。我认为在这种情况下必须这样,因为无论如何这个领域都是静态的。