我有以下课程:
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(), "..");
}
}
}
我需要使用点operadotor获取字典的值,因为我将类设置为参数的类使用dynamic关键字在类上“走”。
例如:
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
成员。
无论如何要解决这个问题非常感谢。提前谢谢。
答案 0 :(得分:7)
您可以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
,您将失去类型安全性 - 您的用例应该能够证明这一缺点 - 通常有更好的方法。
答案 1 :(得分:4)
我认为你应该使用DynamicObject。如果您使用的是旧版本的框架,唯一的选择是 Reflection.Emit
动态是这样的
// 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;
}
答案 2 :(得分:3)
如果您想直接公开Data
成员,则另一个选择是使用ExpandoObject
class,如您的示例所示。如果您不需要定义需要继承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”,尽管我也可以直接分配它:{{1}}。唯一的区别是您可能不知道您拥有的字段名称,前一个示例允许您根据动态输入设置foo.Data.d = "!"
,而后者在您已经知道要使用的字段名称时很有用
答案 3 :(得分:2)
在.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);