문제
C#에는 Python과 같은 것이 있습니까? __getattr__
?
많은 속성을 가진 클래스가 있으며 모두 동일한 액세서 코드를 공유합니다. 파이썬과 마찬가지로 개별 액세서를 완전히 떨어 뜨릴 수 있기를 원합니다.
내 코드는 다음과 같습니다.
class Foo
{
protected bool Get(string name, bool def)
{
try {
return client.Get(name);
} catch {
return def;
}
}
public bool Bar
{
get { return Get("bar", true); }
set { client.Set("bar", value); }
}
public bool Baz
{
get { return Get("baz", false); }
set { client.Set("baz", value); }
}
}
그리고 여기에 내가 원하는 것이 있습니다.
class Foo
{
public bool Get(string name)
{
try {
return client.Get(name);
} catch {
// Look-up default value in hash table and return it
}
}
public void Set(string name, object value)
{
client.Set(name, value)
}
}
전화하지 않고 C#에서 이것을 달성 할 수있는 방법이 있습니까? Get
곧장?
감사,
해결책
아니요. C#은 반사를 지원하지만 읽기 전용 (로드 된 어셈블리의 경우)입니다. 즉, 방법, 속성 또는 기타 메타 데이터를 변경할 수 없습니다. 당신은 할 수 있습니다 동적 속성을 만듭니다, 그것을 부르는 것은 그리 편리하지 않을 것입니다 - 그것은 당신의 사용보다 더 나빠질 것입니다 Get
방법. 사용을 제외하고 Dictionary<string, object>
그리고 당신의 수업의 인덱서, 당신이 할 수있는 일이 많지 않습니다. 어쨌든, 많은 속성이 있다면 사전을 더 잘하지 않습니까?
Python은 속성이 "Compile-Time"(또는 적어도로드 타임)에 존재하는지 확인하지 않습니다. C#. 그것은 두 언어의 근본적인 차이입니다. 파이썬에서는 할 수 있습니다.
class my_class:
pass
my_instance = my_class()
my_instance.my_attr = 1
print(my_instance.my_attr)
C#에서는 C#이 실제로 이름이 확인되므로 그렇게 할 수 없습니다. my_attr
컴파일 타임에 존재합니다.
다른 팁
확실하지 않지만 아마도 버전 4.0의 동적 기능이 도움이 될 것입니다. 그래도 기다려야 할 것입니다 ...
물어봐도 되나요: 왜 개별 속성을 원하지 않습니까? 이것이 바로 객체와 관련된 데이터를 표현하는 관용적 인 .NET 방법입니다.
개인적으로 데이터가 드물지 않다고 가정하면 속성을 유지하고 전반적인 메소드를 사용하여 반사됩니다. 이렇게하면 컴파일 된 코드가 최대한 빨리 만들어집니다.
protected T Get<T>(string name, T @default)
{
var prop = GetType().GetProperty(name);
if(prop == null) return @default;
return (T) prop.GetValue(this, null);
}
물론, 속성 자체가 정의되는 속성에 신경 쓰지 않으면 인덱서와 조회 (예 : 사전)는 괜찮을 것입니다. PostSharp와 함께 할 수있는 일들도 일련의 속성을 속성 백으로 바꾸는 것도 있습니다. 아마도 그만한 가치가 없습니다.
데이터 바인딩 및 런타임 검색에 사용할 수있는 속성을 원하지만 컴파일 타임에 정의 할 수없는 경우 동적 유형 설명자를 살펴 봐야합니다. 어느 하나 ICustomTypeDescriptor
또는 TypeDescriptionProvider
- 상당한 작업이지만 매우 다재다능합니다 (더 많은 정보를 원한다면 알려주세요).
이것은 동적 속성 이름을 가진 파이썬에서 얻는 것과 동일하지 않지만 유용 할 수 있습니다.
using System;
using System.Collections.Generic;
namespace Program
{
class Program
{
static void Main(string[] args)
{
MyList<int> list = new MyList<int>();
// Add a property with setter.
list["One"] = 1;
// Add a property with getter which takes default value.
int two = list["Two", 2];
Console.WriteLine("One={0}", list["One"]);
Console.WriteLine("Two={0} / {1}", two, list["Two"]);
try
{
Console.WriteLine("Three={0}", list["Three"]);
}
catch
{
Console.WriteLine("Three does not exist.");
}
}
class MyList<T>
{
Dictionary<string, T> dictionary = new Dictionary<string,T>();
internal T this[string property, T def]
{
get
{
T value;
if (!dictionary.TryGetValue(property, out value))
dictionary.Add(property, value = def);
return value;
}
}
internal T this[string property]
{
get
{
return dictionary[property];
}
set
{
dictionary[property] = value;
}
}
}
}
}