C#中Python属性定制/JavaScript对象字面量的等价物
我喜欢Python的一个原因是,它可以让你自定义属性的访问方式,具体可以参考这篇文档。
class Foo(object):
def __getattr__(self, name):
if some_predicate(name):
# ...
else:
# Default behaviour
raise AttributeError
在JavaScript中,你也可以用对象字面量的方式更直接地做到类似的事情。
我想问的是:在C#中,怎么能实现类似的功能呢?重载'.'这个操作符是一个方法,但在C#中是不允许的。
我想的例子是定义一个类,像这样:
public class MyClass
{
public IDictionary Properties {get; private set;}
public MyClass(IDictionary properties)
{
this.Properties = properties;
}
// Overload the '.' operator - not allowed!
public static object operator .(MyClass inst, string name)
{
return inst.Properties[name];
}
}
使用这个类的方式如下:
class Program
{
static void Main(string[] args)
{
IDictionary properties = new Dictionary<string, string>() {
{ "prop1", "value1"}, { "prop2", "value2"} };
var my = new MyClass(properties);
System.Console.WriteLine(my.prop1); // Doesn't work!
}
}
(注意:我在这里问过一个关于C++的类似问题这里;最开始是同一个问题,但为了更具体,所以分开了针对每种语言。)
2 个回答
1
@galenus 给了我一个被接受的答案,但为了记录在案,我想把我的示例代码更新一下,使用 DynamicObject。
public class MyClass : DynamicObject
{
public IDictionary<string, object> Properties { get; private set; }
public MyClass(IDictionary<string, object> properties)
{
this.Properties = properties;
}
public override bool TryGetMember(GetMemberBinder binder, out object result)
{
return Properties.TryGetValue(binder.Name, out result);
}
}
class Program
{
static void Main(string[] args)
{
IDictionary<string, object> properties = new Dictionary<string, object>() {
{ "prop1", "value1"}, { "prop2", "value2"} };
dynamic my = new MyClass(properties);
System.Console.WriteLine(my.prop1);
}
}
1
你可以直接使用内置的支持。你应该让你的类继承自DynamicObject,然后重写它的TryGetMember/TrySetMember方法,通过检查构造函数传入的字典来判断属性是否有效。
另一种选择是直接使用ExpandoObject,把它当作一个属性的集合。
不过,虽然你可以获得一些动态语言的功能,但你会失去C#的一些特性,比如类型安全、编译时检查和IDE的代码补全支持。