Как проверить, содержит ли объект зависимости свойство зависимости?

2

По сути, я хочу какое-то простое отражение, где у меня есть произвольный DependencyProperty в качестве параметра. У меня был бы особый случай (например, в выражении if), если DependencyProperty определяется/свойством PlaneProjection. Я сделал несколько простых fandangling из GetType(), но не повезло с ожидаемыми геттерами, такими как MemberType.

public void SomeFunc(DependencyProperty dp)
{
    // if dp is a dependency property of plane projection, do something
    // would maybe look like PlaneProjection.hasProperty(dp)
}
Теги:
silverlight

3 ответа

1
Лучший ответ

Попробуйте использовать этот код с помощью методов расширения:

public static class Helpers
{
    public static DependencyProperty FindDependencyProperty(this DependencyObject target, string propName)
    {
        FieldInfo fInfo = target.GetType().GetField(propName, BindingFlags.Static | BindingFlags.FlattenHierarchy | BindingFlags.Public);

        if (fInfo == null) return null;

        return (DependencyProperty)fInfo.GetValue(null);
    }

    public static bool HasDependencyProperty(this DependencyObject target, string propName)
    {
        return FindDependencyProperty(target, propName) != null;
    }

    public static string GetStaticMemberName<TMemb>(Expression<Func<TMemb>> expression)
    {
        var body = expression.Body as MemberExpression;

        if (body == null) throw new ArgumentException("'expression' should be a member expression");

        return body.Member.Name;
    }
}

Использование:

planeProjection1.HasDependecyProperty(
    Helpers.GetStaticMemberName(() => PlaneProjection.CenterOfRotationXProperty));
  • 0
    Хотя следите за BindingFlags.FlattenHierarchy, если вы хотите обнаруживать только DP, объявленные в этом классе, так как он получает все унаследованные DP, например, из FrameworkElement.
  • 0
    Ну, он их не «получает», он проверяет только все унаследованные поля. Это должно быть значение по умолчанию, чтобы иметь возможность получить «Ширина» и аналогичные унаследованные свойства.
Показать ещё 9 комментариев
1

Означает ли это условие?

Изменить: Только в WPF - не SilverLight.

dp.OwnerType.IsAssignableFrom(typeof(PlaneProjection))
  • 0
    К сожалению это не так. Можно ожидать, что PlaneProjection.CenterOfRotationXProperty.GetType (). IsAssignableFrom (typeof (PlaneProjection) вернет True, но этот вызов всегда возвращает False.
  • 0
    Свойство OwnerType и метод GetType() сильно различаются. Если OwnerType доступен в SilverLight (он есть в WPF), то это то, что вам нужно.
Показать ещё 1 комментарий
0

Это должно позаботиться о ваших потребностях в SilverLight:

private static readonly Dictionary<DependencyProperty, Type> _ownerCache = new Dictionary<DependencyProperty, Type>();
// normally you'd use a HashSet<DependencyProperty>, but it not available in SilverLight
private static readonly Dictionary<Type, Dictionary<DependencyProperty, bool>> _excludeCache = new Dictionary<Type, Dictionary<DependencyProperty, bool>>();

public static bool IsOwnedByTypeOrParent(DependencyProperty dp, Type type)
{
    lock (_ownerCache)
    {
        Type owner;
        if (_ownerCache.TryGetValue(dp, out owner))
            return owner.IsAssignableFrom(type);

        Dictionary<DependencyProperty, bool> exclude;
        if (_excludeCache.TryGetValue(type, out exclude))
        {
            if (exclude.ContainsKey(dp))
                return false;
        }

        FieldInfo[] fields = type.GetFields(BindingFlags.Static | BindingFlags.FlattenHierarchy);
        foreach (FieldInfo field in fields)
        {
            if (typeof(DependencyProperty).IsAssignableFrom(field.FieldType))
            {
                try
                {
                    object value = field.GetValue(null);
                    if (object.ReferenceEquals(dp, value))
                    {
                        _ownerCache[dp] = field.DeclaringType;
                        return true;
                    }
                }
                catch
                {
                }
            }
        }

        if (exclude == null)
        {
            exclude = new Dictionary<DependencyProperty, bool>();
            _excludeCache[type] = exclude;
        }

        exclude.Add(dp, false);

        /* optional if you want to minimize memory overhead. unnecessary unless
         * you are using this on enormous numbers of types/DPs
         */
        foreach (var item in _excludeCache)
        {
            item.Value.Remove(dp);
        }

        return false;
    }
}

Ещё вопросы

Сообщество Overcoder
Наверх
Меню