От вашего комментария: «Я хочу простой и скомпилировать безопасный синтаксис для получения информации о членах».
Это очень часто запрашиваемая функция и обсуждалась на собраниях команды C# в течение примерно десятилетия, но никогда не была приоритетной, настолько высокой, чтобы ее можно было включить.
Этот блог объясняет, почему:
http://blogs.msdn.com/ericlippert/archive/2009/05/21/in-foof-we-trust-a-dialogue.aspx
Так что сейчас, вы только собираетесь бороться против отсутствующей функции.Возможно, вы могли бы разместить дополнительную информацию о своей более широкой проблеме и посмотреть, могут ли люди предлагать разные подходы.
Update
Без дополнительной информации о вашей проблеме это только догадки. Но если у вас есть свойство, которое представляет значение, но также несет дополнительную «мета» информацию, вы всегда можете представить это как новый тип и использовать шаг «инъекции», чтобы все установить.
Вот предложили абстрактный интерфейс к такой «мете собственности»:
public interface IMetaProperty<TValue>
{
TValue Value { get; set; }
string DisplayName { get; }
event Action<TValue, TValue> ValueChanged;
}
Значения свойства просто еще один суб-свойство, с его типом, определенным пользователем.
Я включил отображаемое имя, а также в качестве бонуса у вас есть событие, которое срабатывает при изменении значения (так что вы получаете «наблюдаемость» бесплатно).
Чтобы иметь такие свойства, как это в классе, вы бы объявить его как это:
public class SomeClass
{
public IMetaProperty<string> FirstName { get; private set; }
public IMetaProperty<string> LastName { get; private set; }
public IMetaProperty<int> Age { get; private set; }
public SomeClass() { MetaProperty.Inject(this); }
}
Обратите внимание, как сеттеры по свойствам являются частными. Это останавливает любого пользователя от случайной установки самого свойства вместо установки подэлемента Value.
Так что это означает, что класс должен установить эти свойства, чтобы они были не только null
. Он делает это, вызывая магический Inject
метод, который может работать на любом классе:
public static class MetaProperty
{
// Make it convenient for us to fill in the meta information
private interface IMetaPropertyInit
{
string DisplayName { get; set; }
}
// Implementation of a meta-property
private class MetaPropertyImpl<TValue> : IMetaProperty<TValue>,
IMetaPropertyInit
{
private TValue _value;
public TValue Value
{
get { return _value; }
set
{
var old = _value;
_value = value;
ValueChanged(old, _value);
}
}
public string DisplayName { get; set; }
public event Action<TValue, TValue> ValueChanged = delegate { };
}
public static void Inject(object target)
{
// for each meta property...
foreach (var property in target.GetType().GetProperties()
.Where(p => p.PropertyType.IsGenericType &&
p.PropertyType.GetGenericTypeDefinition()
== typeof(IMetaProperty<>)))
{
// construct an implementation with the correct type
var impl = (IMetaPropertyInit)
typeof (MetaPropertyImpl<>).MakeGenericType(
property.PropertyType.GetGenericArguments()
).GetConstructor(Type.EmptyTypes).Invoke(null);
// initialize any meta info (could examine attributes...)
impl.DisplayName = property.Name;
// set the value
property.SetValue(target, impl, null);
}
}
}
Он просто использует отражение, чтобы найти все IMetaProperty
слотов, скрывающихся в объекте, и заполняет их с реализацией.
Так что теперь пользователь SomeClass
мог сказать:
var sc = new SomeClass
{
FirstName = { Value = "Homer" },
LastName = { Value = "Simpson" },
Age = { Value = 38 },
};
Console.WriteLine(sc.FirstName.DisplayName + " = " + sc.FirstName.Value);
sc.Age.ValueChanged += (from, to) =>
Console.WriteLine("Age changed from " + from + " to " + to);
sc.Age.Value = 39;
// sc.Age = null; compiler would stop this
Если вы уже используете контейнер МОК, вы можете быть в состоянии достичь некоторых из этого не заходя непосредственно к размышлению.
Что именно вы пытаетесь достичь? –
Это статическое отражение над именами участников в типе – saret
Вы не можете создавать статические методы расширения в C# 3. Если это ваш собственный тип, который вы расширяете, почему вы не можете добавить этот метод напрямую? –