使用动态关键字使用.(点)运算符获取字典值,这是可能的
本文关键字:获取 关键字 动态 运算符 字典 | 更新日期: 2023-09-27 18:14:43
我有以下类:
public class foo
{
public Dictionary<string, string> data = new Dictionary<string, string>();
public foo(params object[] args)
{
foreach (object arg in args)
{
data.Add(arg.ToString(), "..");
}
}
}
我需要使用点操作符获得字典的值,这是因为我将类设置为参数的类使用动态关键字在类上"行走"。
例如: var args = new[] {"a","b","c"};
var Foo = new foo(args);
var baa = Foo.data.a;
Console.Write(baa); // ..
存在一种创建动态变量的方法,例如:
public foo(params object[] args) {
foreach (object arg in args) {
var name = (string) arg;
var value = "..";
MakeVariable(name, value);
}
}
将变量命名为arg
,并将值..
作为public
在foo
类中的成员。
以不同的方式解决这个问题是非常赞赏的。
可以让Foo
继承DynamicObject
:
public class Foo : DynamicObject
{
private Dictionary<string, string> data = new Dictionary<string, string>();
public Foo(params object[] args)
{
foreach (object arg in args)
{
data.Add(arg.ToString(), "..");
}
}
public override bool TryGetMember(GetMemberBinder binder, out object result)
{
if (data.ContainsKey(binder.Name))
{
result = data[binder.Name];
return true;
}
return base.TryGetMember(binder, out result);
}
}
可以使用dynamic
来保存Foo
的实例:
var args= new[] { "a", "b", "c" };
dynamic foo = new Foo(args);
var myA = foo.a; //returns ".."
请记住,由于必须使用dynamic
,您将失去类型安全性-您的用例应该真正证明这个缺点-通常有更好的方法。
我认为你应该使用DynamicObject。如果你使用的是旧版本的框架,唯一的选择是Reflection。发出
动态的工作原理是这样的
// If you try to get a value of a property
// not defined in the class, this method is called.
public override bool TryGetMember(
GetMemberBinder binder, out object result)
{
// Converting the property name to lowercase
// so that property names become case-insensitive.
string name = binder.Name.ToLower();
// If the property name is found in a dictionary,
// set the result parameter to the property value and return true.
// Otherwise, return false.
return dictionary.TryGetValue(name, out result);
}
// If you try to set a value of a property that is
// not defined in the class, this method is called.
public override bool TrySetMember(
SetMemberBinder binder, object value)
{
// Converting the property name to lowercase
// so that property names become case-insensitive.
dictionary[binder.Name.ToLower()] = value;
// You can always add a value to a dictionary,
// so this method always returns true.
return true;
}
如果您想要直接公开Data
成员,另一个选择是使用ExpandoObject
类,如您的示例中所示。如果您不需要定义需要继承DynamicObject
的特定操作,这将使代码更简单。
public class Foo
{
public dynamic Data = new ExpandoObject();
public Foo(params object[] args)
{
var dataDict = (IDictionary<string, object>)Data;
foreach (var obj in args)
{
dataDict.Add(obj.ToString(), "..");
}
}
}
用法:
var foo = new Foo("a", "b", "c");
Console.WriteLine(foo.Data.a);
((IDictionary<string, object>)foo.Data).Add("d", "!");
foreach (var item in foo.Data)
{
Console.WriteLine("{0} : {1}", item.Key, item.Value);
}
注意,我转换到一个字典并添加了"d",尽管我也可以直接赋值:foo.Data.d = "!"
。唯一的区别是,您可能事先不知道您有什么字段名,前一个示例允许您基于动态输入设置ExpandoObject
,而后一个示例在您已经知道要使用的字段名时很有用。
在。net 4中,这个确切的行为是由ExpandoObject
类实现的:
public class Foo
{
private readonly ExpandoObject _dict = new ExpandoObject();
public dynamic Data
{
get { return _dict; }
}
public Foo(params object[] args)
{
foreach (var arg in args)
_dict.Add(arg.ToString(), "..");
}
}
var foo = new Foo("a", "b", "c");
foo.Data.x = 3.14;
Console.Write(foo.Data.a);