C# Использование ключевого слова Dynamic для доступа к свойствам через строки без отражения
Я хотел бы написать что-то похожее на следующее:
// I will pass in a number of "properties" specified as strings that I want modified
string[] properties = new [] { "AllowEdit", "AllowDelete" };
// Casting the component I'm using to a dynamic object of some sort ?
dynamic d = myGridComponent;
// Iterate over the strings and set the properties
foreach(var s in properties)
{
//d.s = true; //
//d[s] = true; // this format would be ideal
}
Мне было интересно, есть ли простой способ сделать это без использования Reflection [.GetProperty(...).GetValue(...,...)
] используя новое ключевое слово C# 4.0: dynamic
,
Кажется, что может быть какой-то способ... Я просто не уверен в точном механизме и не смог найти подходящий ресурс, чтобы собрать все части воедино.
Мысли?
[РЕДАКТИРОВАТЬ] Похоже, что есть пакет под названием "Clay", который реализует этот тип функциональности в некотором роде. Клей на CodePlex
Скотт Хансельман по теме
3 ответа
Это может быть сделано. Вы просто должны переопределить TryGetIndex
на DynamicObject
, Мне нужно что-то похожее для вызова статических членов типа, но, надеюсь, вы поймете идею. Имейте в виду, что в настоящее время это не работает с методами с аргументами универсального типа или перегруженными методами, что ограничивает его полезность:
internal class StaticMembersDynamicWrapper : DynamicObject
{
private readonly IDictionary<String, MemberInfo> staticMembers = new Dictionary<string, MemberInfo>();
private readonly Type type;
public StaticMembersDynamicWrapper(Type type)
{
this.type = type;
type.GetMembers(BindingFlags.FlattenHierarchy | BindingFlags.Static | BindingFlags.Public)
.Each(member => staticMembers[member.Name] = member);
}
public override bool TryGetIndex(GetIndexBinder binder, object[] indexes, out object result)
{
var name = indexes[0] as string;
MemberInfo member;
if (false == staticMembers.TryGetValue(name, out member))
{
result = null;
return false;
}
var prop = member as PropertyInfo;
if (prop != null)
{
result = prop.GetValue(null, null);
return true;
}
var method = member as MethodInfo;
if (method != null)
{
var parameterTypes = (from p in method.GetParameters()
select p.ParameterType).ToArray();
var delegateType = method.ReturnType != typeof (void)
? Expression.GetFuncType(parameterTypes.Union(new[]{method.ReturnType}).ToArray())
: Expression.GetActionType(parameterTypes);
result = Delegate.CreateDelegate(delegateType, method);
return true;
}
result = null;
return false;
}
}
dynamic d = new StaticMembersDynamicWrapper(typeof(string));
var result = d["IsNullOrEmpty"](String.Empty);
Нет. dynamic
in C# doesn't offer that. With your two examples:
d.s = true; // this looks for a property or field called "s"
d[s] = true; // this looks for an indexer that matches the string/bool signature
Вы можете написать тот же код, который dynamic
предложения, но это будет намного сложнее, чем просто использование отражения. Либо используйте отражение (согласно вашему примеру), либо, если вам нужно оптимизировать его, вы можете опционально обернуть его в делегат, либо Expression
или же Delegate.CreateDelegate
,
Impromptu-интерфейс с открытым исходным кодом, доступный через nuget, инкапсулирует код, который динамически генерировался бы полностью динамическим способом. Это не так быстро, как использование динамического ключевого слова, но быстрее, чем отражение.
foreach(var s in properties)
{
//d.s = true;
Impromptu.InvokeSet(d, s, true);
}