Wpf markupextension

1.Create a class library project named  CustomMarkupExtension

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Markup;

namespace CustomMarkupExtension
{
    public class RandomExtension : MarkupExtension
    {
        readonly int from, to;
        public RandomExtension(int fromValue,int toValue)
        {
            from = fromValue;
            to= toValue;
        }

        public RandomExtension(int toValue) :this(0, toValue)
        {            
        }

        static readonly Random _rnd = new Random();
        public override object ProvideValue(IServiceProvider serviceProvider)
        {
            return (double)_rnd.Next(from, to);
        }
    }
}

 

2.Rebuild as   dll,and add reference in the main project

3.In the main wpf xaml view.

<Window x:Class="WpfApp8.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:sys="clr-namespace:System;assembly=mscorlib"
        xmlns:local="clr-namespace:WpfApp8"
        xmlns:libModels="http://WpfApp8_Models.com"
        xmlns:lib="http://mylibrary.com"         
        xmlns:mext="clr-namespace:CustomMarkupExtension;assembly=CustomMarkupExtension"
        mc:Ignorable="d" 
        Title="MainWindow" FontSize="20"
        Height="450" Width="800">    
    <StackPanel>
        <TextBlock FontSize="{mext:Random 100}" Text="Hello" x:Name="text1"/>
        <TextBlock x:Name="xt2" Text="{Binding FontSize,ElementName=text1}" 
        FontSize="{Binding Text,ElementName=xt2}" /> 
    </StackPanel>
</Window>

 

Run

 

 

 

 

 

 

DepepdencyProperty implemented source code

#region Assembly WindowsBase, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35
// location unknown
// Decompiled with ICSharpCode.Decompiler 8.1.1.7464
#endregion

using System.Collections;
using System.ComponentModel;
using System.Windows.Markup;
using System.Windows.Threading;
using MS.Internal;
using MS.Internal.WindowsBase;
using MS.Utility;

namespace System.Windows;

//
// Summary:
//     Represents a property that can be set through methods such as, styling, data
//     binding, animation, and inheritance.
[TypeConverter("System.Windows.Markup.DependencyPropertyConverter, PresentationFramework, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, Custom=null")]
[ValueSerializer(typeof(DependencyPropertyValueSerializer))]
public sealed class DependencyProperty
{
    private class FromNameKey
    {
        private string _name;

        private Type _ownerType;

        private int _hashCode;

        public FromNameKey(string name, Type ownerType)
        {
            _name = name;
            _ownerType = ownerType;
            _hashCode = _name.GetHashCode() ^ _ownerType.GetHashCode();
        }

        public void UpdateNameKey(Type ownerType)
        {
            _ownerType = ownerType;
            _hashCode = _name.GetHashCode() ^ _ownerType.GetHashCode();
        }

        public override int GetHashCode()
        {
            return _hashCode;
        }

        public override bool Equals(object o)
        {
            if (o != null && o is FromNameKey)
            {
                return Equals((FromNameKey)o);
            }

            return false;
        }

        public bool Equals(FromNameKey key)
        {
            if (_name.Equals(key._name))
            {
                return _ownerType == key._ownerType;
            }

            return false;
        }
    }

    [Flags]
    private enum Flags
    {
        GlobalIndexMask = 0xFFFF,
        IsValueType = 0x10000,
        IsFreezableType = 0x20000,
        IsStringType = 0x40000,
        IsPotentiallyInherited = 0x80000,
        IsDefaultValueChanged = 0x100000,
        IsPotentiallyUsingDefaultValueFactory = 0x200000,
        IsObjectType = 0x400000
    }

    //
    // Summary:
    //     Specifies a static value that is used by the WPF property system rather than
    //     null to indicate that the property exists, but does not have its value set by
    //     the property system.
    //
    // Returns:
    //     An unset value. This is effectively the result of a call to the System.Object
    //     constructor.
    public static readonly object UnsetValue = new NamedObject("DependencyProperty.UnsetValue");

    private string _name;

    private Type _propertyType;

    private Type _ownerType;

    private PropertyMetadata _defaultMetadata;

    private ValidateValueCallback _validateValueCallback;

    private DependencyPropertyKey _readOnlyKey;

    private Flags _packedData;

    internal InsertionSortMap _metadataMap;

    private CoerceValueCallback _designerCoerceValueCallback;

    internal static ItemStructList<DependencyProperty> RegisteredPropertyList = new ItemStructList<DependencyProperty>(768);

    private static Hashtable PropertyFromName = new Hashtable();

    private static int GlobalIndexCount;

    internal static object Synchronized = new object();

    private static Type NullableType = typeof(Nullable<>);

    //
    // Summary:
    //     Gets the name of the dependency property.
    //
    // Returns:
    //     The name of the property.
    public string Name => _name;

    //
    // Summary:
    //     Gets the type that the dependency property uses for its value.
    //
    // Returns:
    //     The System.Type of the property value.
    public Type PropertyType => _propertyType;

    //
    // Summary:
    //     Gets the type of the object that registered the dependency property with the
    //     property system, or added itself as owner of the property.
    //
    // Returns:
    //     The type of the object that registered the property or added itself as owner
    //     of the property.
    public Type OwnerType => _ownerType;

    //
    // Summary:
    //     Gets the default metadata of the dependency property.
    //
    // Returns:
    //     The default metadata of the dependency property.
    public PropertyMetadata DefaultMetadata => _defaultMetadata;

    //
    // Summary:
    //     Gets the value validation callback for the dependency property.
    //
    // Returns:
    //     The value validation callback for this dependency property, as provided for the
    //     validateValueCallback parameter in the original dependency property registration.
    public ValidateValueCallback ValidateValueCallback => _validateValueCallback;

    //
    // Summary:
    //     Gets an internally generated value that uniquely identifies the dependency property.
    //
    //
    // Returns:
    //     A unique numeric identifier.
    public int GlobalIndex => (int)(_packedData & Flags.GlobalIndexMask);

    internal bool IsObjectType => (_packedData & Flags.IsObjectType) != 0;

    internal bool IsValueType => (_packedData & Flags.IsValueType) != 0;

    internal bool IsFreezableType => (_packedData & Flags.IsFreezableType) != 0;

    internal bool IsStringType => (_packedData & Flags.IsStringType) != 0;

    internal bool IsPotentiallyInherited => (_packedData & Flags.IsPotentiallyInherited) != 0;

    internal bool IsDefaultValueChanged => (_packedData & Flags.IsDefaultValueChanged) != 0;

    internal bool IsPotentiallyUsingDefaultValueFactory => (_packedData & Flags.IsPotentiallyUsingDefaultValueFactory) != 0;

    //
    // Summary:
    //     Gets a value that indicates whether the dependency property identified by this
    //     System.Windows.DependencyProperty instance is a read-only dependency property.
    //
    //
    // Returns:
    //     true if the dependency property is read-only; otherwise, false.
    public bool ReadOnly => _readOnlyKey != null;

    internal DependencyPropertyKey DependencyPropertyKey => _readOnlyKey;

    internal CoerceValueCallback DesignerCoerceValueCallback
    {
        get
        {
            return _designerCoerceValueCallback;
        }
        set
        {
            if (ReadOnly)
            {
                throw new InvalidOperationException(SR.Get("ReadOnlyDesignerCoersionNotAllowed", Name));
            }

            _designerCoerceValueCallback = value;
        }
    }

    internal static int RegisteredPropertyCount => RegisteredPropertyList.Count;

    internal static IEnumerable RegisteredProperties
    {
        get
        {
            DependencyProperty[] list = RegisteredPropertyList.List;
            foreach (DependencyProperty dependencyProperty in list)
            {
                if (dependencyProperty != null)
                {
                    yield return dependencyProperty;
                }
            }
        }
    }

    //
    // Summary:
    //     Registers a dependency property with the specified property name, property type,
    //     and owner type.
    //
    // Parameters:
    //   name:
    //     The name of the dependency property to register. The name must be unique within
    //     the registration namespace of the owner type.
    //
    //   propertyType:
    //     The type of the property.
    //
    //   ownerType:
    //     The owner type that is registering the dependency property.
    //
    // Returns:
    //     A dependency property identifier that should be used to set the value of a public
    //     static readonly field in your class. That identifier is then used to reference
    //     the dependency property later, for operations such as setting its value programmatically
    //     or obtaining metadata.
    public static DependencyProperty Register(string name, Type propertyType, Type ownerType)
    {
        return Register(name, propertyType, ownerType, null, null);
    }

    //
    // Summary:
    //     Registers a dependency property with the specified property name, property type,
    //     owner type, and property metadata.
    //
    // Parameters:
    //   name:
    //     The name of the dependency property to register.
    //
    //   propertyType:
    //     The type of the property.
    //
    //   ownerType:
    //     The owner type that is registering the dependency property.
    //
    //   typeMetadata:
    //     Property metadata for the dependency property.
    //
    // Returns:
    //     A dependency property identifier that should be used to set the value of a public static readonly
    //     field in your class. That identifier is then used to reference the dependency
    //     property later, for operations such as setting its value programmatically or
    //     obtaining metadata.
    public static DependencyProperty Register(string name, Type propertyType, Type ownerType, PropertyMetadata typeMetadata)
    {
        return Register(name, propertyType, ownerType, typeMetadata, null);
    }

    //
    // Summary:
    //     Registers a dependency property with the specified property name, property type,
    //     owner type, property metadata, and a value validation callback for the property.
    //
    //
    // Parameters:
    //   name:
    //     The name of the dependency property to register.
    //
    //   propertyType:
    //     The type of the property.
    //
    //   ownerType:
    //     The owner type that is registering the dependency property.
    //
    //   typeMetadata:
    //     Property metadata for the dependency property.
    //
    //   validateValueCallback:
    //     A reference to a callback that should perform any custom validation of the dependency
    //     property value beyond typical type validation.
    //
    // Returns:
    //     A dependency property identifier that should be used to set the value of a public static readonly
    //     field in your class. That identifier is then used to reference the dependency
    //     property later, for operations such as setting its value programmatically or
    //     obtaining metadata.
    public static DependencyProperty Register(string name, Type propertyType, Type ownerType, PropertyMetadata typeMetadata, ValidateValueCallback validateValueCallback)
    {
        RegisterParameterValidation(name, propertyType, ownerType);
        PropertyMetadata defaultMetadata = null;
        if (typeMetadata != null && typeMetadata.DefaultValueWasSet())
        {
            defaultMetadata = new PropertyMetadata(typeMetadata.DefaultValue);
        }

        DependencyProperty dependencyProperty = RegisterCommon(name, propertyType, ownerType, defaultMetadata, validateValueCallback);
        if (typeMetadata != null)
        {
            dependencyProperty.OverrideMetadata(ownerType, typeMetadata);
        }

        return dependencyProperty;
    }

    //
    // Summary:
    //     Registers a read-only dependency property, with the specified property type,
    //     owner type, and property metadata.
    //
    // Parameters:
    //   name:
    //     The name of the dependency property to register.
    //
    //   propertyType:
    //     The type of the property.
    //
    //   ownerType:
    //     The owner type that is registering the dependency property.
    //
    //   typeMetadata:
    //     Property metadata for the dependency property.
    //
    // Returns:
    //     A dependency property key that should be used to set the value of a static read-only
    //     field in your class, which is then used to reference the dependency property.
    public static DependencyPropertyKey RegisterReadOnly(string name, Type propertyType, Type ownerType, PropertyMetadata typeMetadata)
    {
        return RegisterReadOnly(name, propertyType, ownerType, typeMetadata, null);
    }

    //
    // Summary:
    //     Registers a read-only dependency property, with the specified property type,
    //     owner type, property metadata, and a validation callback.
    //
    // Parameters:
    //   name:
    //     The name of the dependency property to register.
    //
    //   propertyType:
    //     The type of the property.
    //
    //   ownerType:
    //     The owner type that is registering the dependency property.
    //
    //   typeMetadata:
    //     Property metadata for the dependency property.
    //
    //   validateValueCallback:
    //     A reference to a user-created callback that should perform any custom validation
    //     of the dependency property value beyond typical type validation.
    //
    // Returns:
    //     A dependency property key that should be used to set the value of a static read-only
    //     field in your class, which is then used to reference the dependency property
    //     later.
    public static DependencyPropertyKey RegisterReadOnly(string name, Type propertyType, Type ownerType, PropertyMetadata typeMetadata, ValidateValueCallback validateValueCallback)
    {
        RegisterParameterValidation(name, propertyType, ownerType);
        PropertyMetadata propertyMetadata = null;
        propertyMetadata = ((typeMetadata == null || !typeMetadata.DefaultValueWasSet()) ? AutoGeneratePropertyMetadata(propertyType, validateValueCallback, name, ownerType) : new PropertyMetadata(typeMetadata.DefaultValue));
        DependencyPropertyKey dependencyPropertyKey = new DependencyPropertyKey(null);
        DependencyProperty dependencyProperty = RegisterCommon(name, propertyType, ownerType, propertyMetadata, validateValueCallback);
        dependencyProperty._readOnlyKey = dependencyPropertyKey;
        dependencyPropertyKey.SetDependencyProperty(dependencyProperty);
        if (typeMetadata == null)
        {
            typeMetadata = AutoGeneratePropertyMetadata(propertyType, validateValueCallback, name, ownerType);
        }

        dependencyProperty.OverrideMetadata(ownerType, typeMetadata, dependencyPropertyKey);
        return dependencyPropertyKey;
    }

    //
    // Summary:
    //     Registers a read-only attached property, with the specified property type, owner
    //     type, and property metadata.
    //
    // Parameters:
    //   name:
    //     The name of the dependency property to register.
    //
    //   propertyType:
    //     The type of the property.
    //
    //   ownerType:
    //     The owner type that is registering the dependency property.
    //
    //   defaultMetadata:
    //     Property metadata for the dependency property.
    //
    // Returns:
    //     A dependency property key that should be used to set the value of a static read-only
    //     field in your class, which is then used to reference the dependency property
    //     later.
    public static DependencyPropertyKey RegisterAttachedReadOnly(string name, Type propertyType, Type ownerType, PropertyMetadata defaultMetadata)
    {
        return RegisterAttachedReadOnly(name, propertyType, ownerType, defaultMetadata, null);
    }

    //
    // Summary:
    //     Registers a read-only attached property, with the specified property type, owner
    //     type, property metadata, and a validation callback.
    //
    // Parameters:
    //   name:
    //     The name of the dependency property to register.
    //
    //   propertyType:
    //     The type of the property.
    //
    //   ownerType:
    //     The owner type that is registering the dependency property.
    //
    //   defaultMetadata:
    //     Property metadata for the dependency property.
    //
    //   validateValueCallback:
    //     A reference to a user-created callback that should perform any custom validation
    //     of the dependency property value beyond typical type validation.
    //
    // Returns:
    //     A dependency property key that should be used to set the value of a static read-only
    //     field in your class, which is then used to reference the dependency property.
    public static DependencyPropertyKey RegisterAttachedReadOnly(string name, Type propertyType, Type ownerType, PropertyMetadata defaultMetadata, ValidateValueCallback validateValueCallback)
    {
        RegisterParameterValidation(name, propertyType, ownerType);
        if (defaultMetadata == null)
        {
            defaultMetadata = AutoGeneratePropertyMetadata(propertyType, validateValueCallback, name, ownerType);
        }

        DependencyPropertyKey dependencyPropertyKey = new DependencyPropertyKey(null);
        DependencyProperty dependencyProperty = RegisterCommon(name, propertyType, ownerType, defaultMetadata, validateValueCallback);
        dependencyProperty._readOnlyKey = dependencyPropertyKey;
        dependencyPropertyKey.SetDependencyProperty(dependencyProperty);
        return dependencyPropertyKey;
    }

    //
    // Summary:
    //     Registers an attached property with the specified property name, property type,
    //     and owner type.
    //
    // Parameters:
    //   name:
    //     The name of the dependency property to register.
    //
    //   propertyType:
    //     The type of the property.
    //
    //   ownerType:
    //     The owner type that is registering the dependency property.
    //
    // Returns:
    //     A dependency property identifier that should be used to set the value of a public static readonly
    //     field in your class. That identifier is then used to reference the dependency
    //     property later, for operations such as setting its value programmatically or
    //     obtaining metadata.
    public static DependencyProperty RegisterAttached(string name, Type propertyType, Type ownerType)
    {
        return RegisterAttached(name, propertyType, ownerType, null, null);
    }

    //
    // Summary:
    //     Registers an attached property with the specified property name, property type,
    //     owner type, and property metadata.
    //
    // Parameters:
    //   name:
    //     The name of the dependency property to register.
    //
    //   propertyType:
    //     The type of the property.
    //
    //   ownerType:
    //     The owner type that is registering the dependency property.
    //
    //   defaultMetadata:
    //     Property metadata for the dependency property. This can include the default value
    //     as well as other characteristics.
    //
    // Returns:
    //     A dependency property identifier that should be used to set the value of a public static readonly
    //     field in your class. That identifier is then used to reference the dependency
    //     property later, for operations such as setting its value programmatically or
    //     obtaining metadata.
    public static DependencyProperty RegisterAttached(string name, Type propertyType, Type ownerType, PropertyMetadata defaultMetadata)
    {
        return RegisterAttached(name, propertyType, ownerType, defaultMetadata, null);
    }

    //
    // Summary:
    //     Registers an attached property with the specified property type, owner type,
    //     property metadata, and value validation callback for the property.
    //
    // Parameters:
    //   name:
    //     The name of the dependency property to register.
    //
    //   propertyType:
    //     The type of the property.
    //
    //   ownerType:
    //     The owner type that is registering the dependency property.
    //
    //   defaultMetadata:
    //     Property metadata for the dependency property. This can include the default value
    //     as well as other characteristics.
    //
    //   validateValueCallback:
    //     A reference to a callback that should perform any custom validation of the dependency
    //     property value beyond typical type validation.
    //
    // Returns:
    //     A dependency property identifier that should be used to set the value of a public
    //     static readonly field in your class. That identifier is then used to reference
    //     the dependency property later, for operations such as setting its value programmatically
    //     or obtaining metadata.
    public static DependencyProperty RegisterAttached(string name, Type propertyType, Type ownerType, PropertyMetadata defaultMetadata, ValidateValueCallback validateValueCallback)
    {
        RegisterParameterValidation(name, propertyType, ownerType);
        return RegisterCommon(name, propertyType, ownerType, defaultMetadata, validateValueCallback);
    }

    private static void RegisterParameterValidation(string name, Type propertyType, Type ownerType)
    {
        if (name == null)
        {
            throw new ArgumentNullException("name");
        }

        if (name.Length == 0)
        {
            throw new ArgumentException(SR.Get("StringEmpty"), "name");
        }

        if (ownerType == null)
        {
            throw new ArgumentNullException("ownerType");
        }

        if (propertyType == null)
        {
            throw new ArgumentNullException("propertyType");
        }
    }

    private static DependencyProperty RegisterCommon(string name, Type propertyType, Type ownerType, PropertyMetadata defaultMetadata, ValidateValueCallback validateValueCallback)
    {
        FromNameKey key = new FromNameKey(name, ownerType);
        lock (Synchronized)
        {
            if (PropertyFromName.Contains(key))
            {
                throw new ArgumentException(SR.Get("PropertyAlreadyRegistered", name, ownerType.Name));
            }
        }

        if (defaultMetadata == null)
        {
            defaultMetadata = AutoGeneratePropertyMetadata(propertyType, validateValueCallback, name, ownerType);
        }
        else
        {
            if (!defaultMetadata.DefaultValueWasSet())
            {
                defaultMetadata.DefaultValue = AutoGenerateDefaultValue(propertyType);
            }

            ValidateMetadataDefaultValue(defaultMetadata, propertyType, name, validateValueCallback);
        }

        DependencyProperty dependencyProperty = new DependencyProperty(name, propertyType, ownerType, defaultMetadata, validateValueCallback);
        defaultMetadata.Seal(dependencyProperty, null);
        if (defaultMetadata.IsInherited)
        {
            dependencyProperty._packedData |= Flags.IsPotentiallyInherited;
        }

        if (defaultMetadata.UsingDefaultValueFactory)
        {
            dependencyProperty._packedData |= Flags.IsPotentiallyUsingDefaultValueFactory;
        }

        lock (Synchronized)
        {
            PropertyFromName[key] = dependencyProperty;
        }

        if (TraceDependencyProperty.IsEnabled)
        {
            TraceDependencyProperty.TraceActivityItem(TraceDependencyProperty.Register, dependencyProperty, dependencyProperty.OwnerType);
        }

        return dependencyProperty;
    }

    private static object AutoGenerateDefaultValue(Type propertyType)
    {
        object result = null;
        if (propertyType.IsValueType)
        {
            result = Activator.CreateInstance(propertyType);
        }

        return result;
    }

    private static PropertyMetadata AutoGeneratePropertyMetadata(Type propertyType, ValidateValueCallback validateValueCallback, string name, Type ownerType)
    {
        object obj = AutoGenerateDefaultValue(propertyType);
        if (validateValueCallback != null && !validateValueCallback(obj))
        {
            throw new ArgumentException(SR.Get("DefaultValueAutoAssignFailed", name, ownerType.Name));
        }

        return new PropertyMetadata(obj);
    }

    private static void ValidateMetadataDefaultValue(PropertyMetadata defaultMetadata, Type propertyType, string propertyName, ValidateValueCallback validateValueCallback)
    {
        if (!defaultMetadata.UsingDefaultValueFactory)
        {
            ValidateDefaultValueCommon(defaultMetadata.DefaultValue, propertyType, propertyName, validateValueCallback, checkThreadAffinity: true);
        }
    }

    internal void ValidateFactoryDefaultValue(object defaultValue)
    {
        ValidateDefaultValueCommon(defaultValue, PropertyType, Name, ValidateValueCallback, checkThreadAffinity: false);
    }

    private static void ValidateDefaultValueCommon(object defaultValue, Type propertyType, string propertyName, ValidateValueCallback validateValueCallback, bool checkThreadAffinity)
    {
        if (!IsValidType(defaultValue, propertyType))
        {
            throw new ArgumentException(SR.Get("DefaultValuePropertyTypeMismatch", propertyName));
        }

        if (defaultValue is Expression)
        {
            throw new ArgumentException(SR.Get("DefaultValueMayNotBeExpression"));
        }

        if (checkThreadAffinity && defaultValue is DispatcherObject dispatcherObject && dispatcherObject.Dispatcher != null)
        {
            if (!(dispatcherObject is ISealable sealable) || !sealable.CanSeal)
            {
                throw new ArgumentException(SR.Get("DefaultValueMustBeFreeThreaded", propertyName));
            }

            Invariant.Assert(!sealable.IsSealed, "A Sealed ISealable must not have dispatcher affinity");
            sealable.Seal();
            Invariant.Assert(dispatcherObject.Dispatcher == null, "ISealable.Seal() failed after ISealable.CanSeal returned true");
        }

        if (validateValueCallback != null && !validateValueCallback(defaultValue))
        {
            throw new ArgumentException(SR.Get("DefaultValueInvalid", propertyName));
        }
    }

    private void SetupOverrideMetadata(Type forType, PropertyMetadata typeMetadata, out DependencyObjectType dType, out PropertyMetadata baseMetadata)
    {
        if (forType == null)
        {
            throw new ArgumentNullException("forType");
        }

        if (typeMetadata == null)
        {
            throw new ArgumentNullException("typeMetadata");
        }

        if (typeMetadata.Sealed)
        {
            throw new ArgumentException(SR.Get("TypeMetadataAlreadyInUse"));
        }

        if (!typeof(DependencyObject).IsAssignableFrom(forType))
        {
            throw new ArgumentException(SR.Get("TypeMustBeDependencyObjectDerived", forType.Name));
        }

        if (typeMetadata.IsDefaultValueModified)
        {
            ValidateMetadataDefaultValue(typeMetadata, PropertyType, Name, ValidateValueCallback);
        }

        dType = DependencyObjectType.FromSystemType(forType);
        baseMetadata = GetMetadata(dType.BaseType);
        if (!baseMetadata.GetType().IsAssignableFrom(typeMetadata.GetType()))
        {
            throw new ArgumentException(SR.Get("OverridingMetadataDoesNotMatchBaseMetadataType"));
        }
    }

    //
    // Summary:
    //     Specifies alternate metadata for this dependency property when it is present
    //     on instances of a specified type, overriding the metadata that existed for the
    //     dependency property as it was inherited from base types.
    //
    // Parameters:
    //   forType:
    //     The type where this dependency property is inherited and where the provided alternate
    //     metadata will be applied.
    //
    //   typeMetadata:
    //     The metadata to apply to the dependency property on the overriding type.
    //
    // Exceptions:
    //   T:System.InvalidOperationException:
    //     An attempt was made to override metadata on a read-only dependency property (that
    //     operation cannot be done using this signature).
    //
    //   T:System.ArgumentException:
    //     Metadata was already established for the dependency property as it exists on
    //     the provided type.
    public void OverrideMetadata(Type forType, PropertyMetadata typeMetadata)
    {
        SetupOverrideMetadata(forType, typeMetadata, out var dType, out var baseMetadata);
        if (ReadOnly)
        {
            throw new InvalidOperationException(SR.Get("ReadOnlyOverrideNotAllowed", Name));
        }

        ProcessOverrideMetadata(forType, typeMetadata, dType, baseMetadata);
    }

    //
    // Summary:
    //     Supplies alternate metadata for a read-only dependency property when it is present
    //     on instances of a specified type, overriding the metadata that was provided in
    //     the initial dependency property registration. You must pass the System.Windows.DependencyPropertyKey
    //     for the read-only dependency property to avoid raising an exception.
    //
    // Parameters:
    //   forType:
    //     The type where this dependency property is inherited and where the provided alternate
    //     metadata will be applied.
    //
    //   typeMetadata:
    //     The metadata to apply to the dependency property on the overriding type.
    //
    //   key:
    //     The access key for a read-only dependency property.
    public void OverrideMetadata(Type forType, PropertyMetadata typeMetadata, DependencyPropertyKey key)
    {
        SetupOverrideMetadata(forType, typeMetadata, out var dType, out var baseMetadata);
        if (key == null)
        {
            throw new ArgumentNullException("key");
        }

        if (ReadOnly)
        {
            if (key.DependencyProperty != this)
            {
                throw new ArgumentException(SR.Get("ReadOnlyOverrideKeyNotAuthorized", Name));
            }

            VerifyReadOnlyKey(key);
            ProcessOverrideMetadata(forType, typeMetadata, dType, baseMetadata);
            return;
        }

        throw new InvalidOperationException(SR.Get("PropertyNotReadOnly"));
    }

    private void ProcessOverrideMetadata(Type forType, PropertyMetadata typeMetadata, DependencyObjectType dType, PropertyMetadata baseMetadata)
    {
        lock (Synchronized)
        {
            if (UnsetValue != _metadataMap[dType.Id])
            {
                throw new ArgumentException(SR.Get("TypeMetadataAlreadyRegistered", forType.Name));
            }

            _metadataMap[dType.Id] = typeMetadata;
        }

        typeMetadata.InvokeMerge(baseMetadata, this);
        typeMetadata.Seal(this, forType);
        if (typeMetadata.IsInherited)
        {
            _packedData |= Flags.IsPotentiallyInherited;
        }

        if (typeMetadata.DefaultValueWasSet() && typeMetadata.DefaultValue != DefaultMetadata.DefaultValue)
        {
            _packedData |= Flags.IsDefaultValueChanged;
        }

        if (typeMetadata.UsingDefaultValueFactory)
        {
            _packedData |= Flags.IsPotentiallyUsingDefaultValueFactory;
        }
    }

    [FriendAccessAllowed]
    internal object GetDefaultValue(DependencyObjectType dependencyObjectType)
    {
        if (!IsDefaultValueChanged)
        {
            return DefaultMetadata.DefaultValue;
        }

        return GetMetadata(dependencyObjectType).DefaultValue;
    }

    [FriendAccessAllowed]
    internal object GetDefaultValue(Type forType)
    {
        if (!IsDefaultValueChanged)
        {
            return DefaultMetadata.DefaultValue;
        }

        return GetMetadata(DependencyObjectType.FromSystemTypeInternal(forType)).DefaultValue;
    }

    //
    // Summary:
    //     Returns the metadata for this dependency property as it exists on a specified
    //     existing type.
    //
    // Parameters:
    //   forType:
    //     The specific type from which to retrieve the dependency property metadata.
    //
    // Returns:
    //     A property metadata object.
    public PropertyMetadata GetMetadata(Type forType)
    {
        if (forType != null)
        {
            return GetMetadata(DependencyObjectType.FromSystemType(forType));
        }

        throw new ArgumentNullException("forType");
    }

    //
    // Summary:
    //     Returns the metadata for this dependency property as it exists on the specified
    //     object instance.
    //
    // Parameters:
    //   dependencyObject:
    //     A dependency object that is checked for type, to determine which type-specific
    //     version of the dependency property the metadata should come from.
    //
    // Returns:
    //     A property metadata object.
    public PropertyMetadata GetMetadata(DependencyObject dependencyObject)
    {
        if (dependencyObject != null)
        {
            return GetMetadata(dependencyObject.DependencyObjectType);
        }

        throw new ArgumentNullException("dependencyObject");
    }

    //
    // Summary:
    //     Returns the metadata for this dependency property as it exists on a specified
    //     type.
    //
    // Parameters:
    //   dependencyObjectType:
    //     A specific object that records the dependency object type from which the dependency
    //     property metadata is desired.
    //
    // Returns:
    //     A property metadata object.
    public PropertyMetadata GetMetadata(DependencyObjectType dependencyObjectType)
    {
        if (dependencyObjectType != null)
        {
            int num = _metadataMap.Count - 1;
            if (num < 0)
            {
                return _defaultMetadata;
            }

            int key;
            object value;
            if (num == 0)
            {
                _metadataMap.GetKeyValuePair(num, out key, out value);
                while (dependencyObjectType.Id > key)
                {
                    dependencyObjectType = dependencyObjectType.BaseType;
                }

                if (key == dependencyObjectType.Id)
                {
                    return (PropertyMetadata)value;
                }
            }
            else if (dependencyObjectType.Id != 0)
            {
                do
                {
                    _metadataMap.GetKeyValuePair(num, out key, out value);
                    num--;
                    while (dependencyObjectType.Id < key && num >= 0)
                    {
                        _metadataMap.GetKeyValuePair(num, out key, out value);
                        num--;
                    }

                    while (dependencyObjectType.Id > key)
                    {
                        dependencyObjectType = dependencyObjectType.BaseType;
                    }

                    if (key == dependencyObjectType.Id)
                    {
                        return (PropertyMetadata)value;
                    }
                }
                while (num >= 0);
            }
        }

        return _defaultMetadata;
    }

    //
    // Summary:
    //     Adds another type as an owner of a dependency property that has already been
    //     registered.
    //
    // Parameters:
    //   ownerType:
    //     The type to add as an owner of this dependency property.
    //
    // Returns:
    //     A reference to the original System.Windows.DependencyProperty identifier that
    //     identifies the dependency property. This identifier should be exposed by the
    //     adding class as a public static readonly field.
    public DependencyProperty AddOwner(Type ownerType)
    {
        return AddOwner(ownerType, null);
    }

    //
    // Summary:
    //     Adds another type as an owner of a dependency property that has already been
    //     registered, providing dependency property metadata for the dependency property
    //     as it will exist on the provided owner type.
    //
    // Parameters:
    //   ownerType:
    //     The type to add as owner of this dependency property.
    //
    //   typeMetadata:
    //     The metadata that qualifies the dependency property as it exists on the provided
    //     type.
    //
    // Returns:
    //     A reference to the original System.Windows.DependencyProperty identifier that
    //     identifies the dependency property. This identifier should be exposed by the
    //     adding class as a public static readonly field.
    public DependencyProperty AddOwner(Type ownerType, PropertyMetadata typeMetadata)
    {
        if (ownerType == null)
        {
            throw new ArgumentNullException("ownerType");
        }

        FromNameKey key = new FromNameKey(Name, ownerType);
        lock (Synchronized)
        {
            if (PropertyFromName.Contains(key))
            {
                throw new ArgumentException(SR.Get("PropertyAlreadyRegistered", Name, ownerType.Name));
            }
        }

        if (typeMetadata != null)
        {
            OverrideMetadata(ownerType, typeMetadata);
        }

        lock (Synchronized)
        {
            PropertyFromName[key] = this;
            return this;
        }
    }

    //
    // Summary:
    //     Returns a hash code for this System.Windows.DependencyProperty.
    //
    // Returns:
    //     The hash code for this System.Windows.DependencyProperty.
    public override int GetHashCode()
    {
        return GlobalIndex;
    }

    //
    // Summary:
    //     Determines whether a specified value is acceptable for this dependency property's
    //     type, as checked against the property type provided in the original dependency
    //     property registration.
    //
    // Parameters:
    //   value:
    //     The value to check.
    //
    // Returns:
    //     true if the specified value is the registered property type or an acceptable
    //     derived type; otherwise, false.
    public bool IsValidType(object value)
    {
        return IsValidType(value, PropertyType);
    }

    //
    // Summary:
    //     Determines whether the provided value is accepted for the type of property through
    //     basic type checking, and also potentially if it is within the allowed range of
    //     values for that type.
    //
    // Parameters:
    //   value:
    //     The value to check.
    //
    // Returns:
    //     true if the value is acceptable and is of the correct type or a derived type;
    //     otherwise, false.
    public bool IsValidValue(object value)
    {
        if (!IsValidType(value, PropertyType))
        {
            return false;
        }

        if (ValidateValueCallback != null)
        {
            return ValidateValueCallback(value);
        }

        return true;
    }

    internal void VerifyReadOnlyKey(DependencyPropertyKey candidateKey)
    {
        if (_readOnlyKey != candidateKey)
        {
            throw new ArgumentException(SR.Get("ReadOnlyKeyNotAuthorized"));
        }
    }

    internal bool IsValidValueInternal(object value)
    {
        if (ValidateValueCallback != null)
        {
            return ValidateValueCallback(value);
        }

        return true;
    }

    [FriendAccessAllowed]
    internal static DependencyProperty FromName(string name, Type ownerType)
    {
        DependencyProperty dependencyProperty = null;
        if (name != null)
        {
            if (ownerType != null)
            {
                FromNameKey fromNameKey = new FromNameKey(name, ownerType);
                while (dependencyProperty == null && ownerType != null)
                {
                    SecurityHelper.RunClassConstructor(ownerType);
                    fromNameKey.UpdateNameKey(ownerType);
                    lock (Synchronized)
                    {
                        dependencyProperty = (DependencyProperty)PropertyFromName[fromNameKey];
                    }

                    ownerType = ownerType.BaseType;
                }

                return dependencyProperty;
            }

            throw new ArgumentNullException("ownerType");
        }

        throw new ArgumentNullException("name");
    }

    //
    // Summary:
    //     Returns the string representation of the dependency property.
    //
    // Returns:
    //     The string representation of the dependency property.
    public override string ToString()
    {
        return _name;
    }

    internal static bool IsValidType(object value, Type propertyType)
    {
        if (value == null)
        {
            if (propertyType.IsValueType && (!propertyType.IsGenericType || !(propertyType.GetGenericTypeDefinition() == NullableType)))
            {
                return false;
            }
        }
        else if (!propertyType.IsInstanceOfType(value))
        {
            return false;
        }

        return true;
    }

    private DependencyProperty(string name, Type propertyType, Type ownerType, PropertyMetadata defaultMetadata, ValidateValueCallback validateValueCallback)
    {
        _name = name;
        _propertyType = propertyType;
        _ownerType = ownerType;
        _defaultMetadata = defaultMetadata;
        _validateValueCallback = validateValueCallback;
        Flags flags;
        lock (Synchronized)
        {
            flags = (Flags)GetUniqueGlobalIndex(ownerType, name);
            RegisteredPropertyList.Add(this);
        }

        if (propertyType.IsValueType)
        {
            flags |= Flags.IsValueType;
        }

        if (propertyType == typeof(object))
        {
            flags |= Flags.IsObjectType;
        }

        if (typeof(Freezable).IsAssignableFrom(propertyType))
        {
            flags |= Flags.IsFreezableType;
        }

        if (propertyType == typeof(string))
        {
            flags |= Flags.IsStringType;
        }

        _packedData = flags;
    }

    internal static int GetUniqueGlobalIndex(Type ownerType, string name)
    {
        if (GlobalIndexCount >= 65535)
        {
            if (ownerType != null)
            {
                throw new InvalidOperationException(SR.Get("TooManyDependencyProperties", ownerType.Name + "." + name));
            }

            throw new InvalidOperationException(SR.Get("TooManyDependencyProperties", "ConstantProperty"));
        }

        return GlobalIndexCount++;
    }
}
#if false // Decompilation log
'14' items in cache
------------------
Resolve: 'mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'
Found single assembly: 'mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'
Load from: 'C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.8\mscorlib.dll'
------------------
Resolve: 'System.Xaml, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'
Found single assembly: 'System.Xaml, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'
Load from: 'C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.8\System.Xaml.dll'
------------------
Resolve: 'System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'
Found single assembly: 'System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'
Load from: 'C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.8\System.dll'
------------------
Resolve: 'Accessibility, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'
Could not find by name: 'Accessibility, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'
------------------
Resolve: 'System.Core, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'
Found single assembly: 'System.Core, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'
Load from: 'C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.8\System.Core.dll'
------------------
Resolve: 'System.Xml, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'
Found single assembly: 'System.Xml, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'
Load from: 'C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.8\System.Xml.dll'
------------------
Resolve: 'System.Security, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'
Could not find by name: 'System.Security, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'
------------------
Resolve: 'System.Configuration, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'
Could not find by name: 'System.Configuration, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'
#endif

 

posted @ 2024-03-18 17:00  FredGrit  阅读(10)  评论(0编辑  收藏  举报