17 changed files with 707 additions and 396 deletions
@ -0,0 +1,67 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Text; |
|||
using Avalonia.Data; |
|||
using Avalonia.Data.Core.Plugins; |
|||
|
|||
namespace Avalonia.Markup.Xaml.MarkupExtensions.CompiledBindings |
|||
{ |
|||
class ArrayElementPlugin : IPropertyAccessorPlugin |
|||
{ |
|||
private readonly int[] _indices; |
|||
private readonly Type _elementType; |
|||
|
|||
public ArrayElementPlugin(int[] indices, Type elementType) |
|||
{ |
|||
_indices = indices; |
|||
_elementType = elementType; |
|||
} |
|||
|
|||
public bool Match(object obj, string propertyName) |
|||
{ |
|||
throw new InvalidOperationException("The ArrayElementPlugin does not support dynamic matching"); |
|||
} |
|||
|
|||
public IPropertyAccessor Start(WeakReference reference, string propertyName) |
|||
{ |
|||
return new Accessor(reference, _indices, _elementType); |
|||
} |
|||
|
|||
class Accessor : PropertyAccessorBase |
|||
{ |
|||
private readonly int[] _indices; |
|||
private readonly WeakReference _reference; |
|||
|
|||
public Accessor(WeakReference reference, int[] indices, Type elementType) |
|||
{ |
|||
_reference = reference; |
|||
_indices = indices; |
|||
PropertyType = elementType; |
|||
} |
|||
|
|||
public override Type PropertyType { get; } |
|||
|
|||
public override object Value => _reference.Target is Array arr ? arr.GetValue(_indices) : null; |
|||
|
|||
public override bool SetValue(object value, BindingPriority priority) |
|||
{ |
|||
if (_reference.Target is Array arr) |
|||
{ |
|||
arr.SetValue(value, _indices); |
|||
return true; |
|||
} |
|||
return false; |
|||
} |
|||
|
|||
protected override void SubscribeCore() |
|||
{ |
|||
PublishValue(Value); |
|||
} |
|||
|
|||
protected override void UnsubscribeCore() |
|||
{ |
|||
} |
|||
} |
|||
} |
|||
|
|||
} |
|||
@ -1,255 +0,0 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Collections.Specialized; |
|||
using System.ComponentModel; |
|||
using System.Diagnostics; |
|||
using System.Runtime.CompilerServices; |
|||
using System.Text; |
|||
using Avalonia.Data.Core; |
|||
using Avalonia.Reactive; |
|||
using Avalonia.Utilities; |
|||
|
|||
namespace Avalonia.Markup.Xaml.MarkupExtensions.CompiledBindings |
|||
{ |
|||
public static class NotifyingPropertyInfoHelpers |
|||
{ |
|||
public static INotifyingPropertyInfo CreateINPCPropertyInfo(IPropertyInfo basePropertyInfo) |
|||
=> new INPCPropertyInfo(basePropertyInfo); |
|||
|
|||
public static INotifyingPropertyInfo CreateAvaloniaPropertyInfo(AvaloniaProperty property) |
|||
=> new AvaloniaPropertyInfo(property); |
|||
|
|||
public static INotifyingPropertyInfo CreateIndexerPropertyInfo(IPropertyInfo basePropertyInfo, int argument) |
|||
=> new IndexerInfo(basePropertyInfo, argument); |
|||
} |
|||
|
|||
public interface INotifyingPropertyInfo : IPropertyInfo |
|||
{ |
|||
void OnPropertyChanged(object target, EventHandler handler); |
|||
void RemoveListener(object target, EventHandler handler); |
|||
} |
|||
|
|||
internal abstract class NotifyingPropertyInfoBase : INotifyingPropertyInfo |
|||
{ |
|||
private readonly IPropertyInfo _base; |
|||
protected readonly ConditionalWeakTable<object, EventHandler> _changedHandlers = new ConditionalWeakTable<object, EventHandler>(); |
|||
|
|||
public NotifyingPropertyInfoBase(IPropertyInfo baseProperty) |
|||
{ |
|||
_base = baseProperty; |
|||
} |
|||
|
|||
public string Name => _base.Name; |
|||
|
|||
public bool CanSet => _base.CanSet; |
|||
|
|||
public bool CanGet => _base.CanGet; |
|||
|
|||
public Type PropertyType => _base.PropertyType; |
|||
|
|||
public object Get(object target) |
|||
{ |
|||
return _base.Get(target); |
|||
} |
|||
|
|||
public void Set(object target, object value) |
|||
{ |
|||
_base.Set(target, value); |
|||
} |
|||
|
|||
public void OnPropertyChanged(object target, EventHandler handler) |
|||
{ |
|||
if (ValidateTargetType(target)) |
|||
{ |
|||
return; |
|||
} |
|||
|
|||
if (_changedHandlers.TryGetValue(target, out var value)) |
|||
{ |
|||
_changedHandlers.Remove(target); |
|||
_changedHandlers.Add(target, (EventHandler)Delegate.Combine(value, handler)); |
|||
} |
|||
else |
|||
{ |
|||
_changedHandlers.Add(target, handler); |
|||
SubscribeToChangesForNewTarget(target); |
|||
} |
|||
} |
|||
|
|||
protected abstract bool ValidateTargetType(object target); |
|||
|
|||
protected abstract void SubscribeToChangesForNewTarget(object target); |
|||
|
|||
protected abstract void UnsubscribeToChangesForTarget(object target); |
|||
|
|||
protected bool TryGetHandlersForTarget(object target, out EventHandler handlers) |
|||
=> _changedHandlers.TryGetValue(target, out handlers); |
|||
|
|||
public void RemoveListener(object target, EventHandler handler) |
|||
{ |
|||
if (!ValidateTargetType(target)) |
|||
{ |
|||
return; |
|||
} |
|||
|
|||
if (_changedHandlers.TryGetValue(target, out var value)) |
|||
{ |
|||
_changedHandlers.Remove(target); |
|||
EventHandler modified = (EventHandler)Delegate.Remove(value, handler); |
|||
if (modified != null) |
|||
{ |
|||
_changedHandlers.Add(target, modified); |
|||
} |
|||
else |
|||
{ |
|||
UnsubscribeToChangesForTarget(target); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
internal class INPCPropertyInfo : NotifyingPropertyInfoBase |
|||
{ |
|||
public INPCPropertyInfo(IPropertyInfo baseProperty) |
|||
:base(baseProperty) |
|||
{ |
|||
} |
|||
|
|||
void OnNotifyPropertyChanged(object sender, PropertyChangedEventArgs e) |
|||
{ |
|||
if (Name == e.PropertyName && TryGetHandlersForTarget(sender, out var handlers)) |
|||
{ |
|||
handlers(sender, EventArgs.Empty); |
|||
} |
|||
} |
|||
|
|||
protected override bool ValidateTargetType(object target) |
|||
{ |
|||
return target is INotifyPropertyChanged; |
|||
} |
|||
|
|||
protected override void SubscribeToChangesForNewTarget(object target) |
|||
{ |
|||
if (target is INotifyPropertyChanged inpc) |
|||
{ |
|||
WeakEventHandlerManager.Subscribe<INotifyPropertyChanged, PropertyChangedEventArgs, INPCPropertyInfo>( |
|||
inpc, |
|||
nameof(INotifyPropertyChanged.PropertyChanged), |
|||
OnNotifyPropertyChanged); |
|||
} |
|||
} |
|||
|
|||
protected override void UnsubscribeToChangesForTarget(object target) |
|||
{ |
|||
if (target is INotifyPropertyChanged) |
|||
{ |
|||
WeakEventHandlerManager.Unsubscribe<PropertyChangedEventArgs, INPCPropertyInfo>( |
|||
target, |
|||
nameof(INotifyPropertyChanged.PropertyChanged), |
|||
OnNotifyPropertyChanged); |
|||
} |
|||
} |
|||
} |
|||
|
|||
internal class AvaloniaPropertyInfo : NotifyingPropertyInfoBase |
|||
{ |
|||
private readonly AvaloniaProperty _base; |
|||
|
|||
public AvaloniaPropertyInfo(AvaloniaProperty baseProperty) |
|||
:base(baseProperty) |
|||
{ |
|||
_base = baseProperty; |
|||
} |
|||
|
|||
protected override void SubscribeToChangesForNewTarget(object target) |
|||
{ |
|||
IAvaloniaObject obj = (IAvaloniaObject)target; |
|||
obj.PropertyChanged += OnPropertyChanged; |
|||
} |
|||
|
|||
private void OnPropertyChanged(object sender, AvaloniaPropertyChangedEventArgs e) |
|||
{ |
|||
if (_base == e.Property && TryGetHandlersForTarget(sender, out var handlers)) |
|||
{ |
|||
handlers(sender, EventArgs.Empty); |
|||
} |
|||
} |
|||
|
|||
protected override void UnsubscribeToChangesForTarget(object target) |
|||
{ |
|||
((IAvaloniaObject)target).PropertyChanged -= OnPropertyChanged; |
|||
} |
|||
|
|||
protected override bool ValidateTargetType(object target) |
|||
{ |
|||
return target is IAvaloniaObject; |
|||
} |
|||
} |
|||
|
|||
internal class IndexerInfo : INPCPropertyInfo |
|||
{ |
|||
private int _index; |
|||
|
|||
public IndexerInfo(IPropertyInfo baseProperty, int indexerArgument) : base(baseProperty) |
|||
{ |
|||
_index = indexerArgument; |
|||
} |
|||
|
|||
protected override void SubscribeToChangesForNewTarget(object target) |
|||
{ |
|||
base.SubscribeToChangesForNewTarget(target); |
|||
if (target is INotifyCollectionChanged incc) |
|||
{ |
|||
WeakEventHandlerManager.Subscribe<INotifyCollectionChanged, NotifyCollectionChangedEventArgs, IndexerInfo>( |
|||
incc, |
|||
nameof(INotifyCollectionChanged.CollectionChanged), |
|||
OnNotifyCollectionChanged); |
|||
} |
|||
} |
|||
|
|||
protected override void UnsubscribeToChangesForTarget(object target) |
|||
{ |
|||
base.UnsubscribeToChangesForTarget(target); |
|||
if (target is INotifyCollectionChanged) |
|||
{ |
|||
WeakEventHandlerManager.Unsubscribe<NotifyCollectionChangedEventArgs, IndexerInfo>( |
|||
target, |
|||
nameof(INotifyCollectionChanged.CollectionChanged), |
|||
OnNotifyCollectionChanged); |
|||
} |
|||
} |
|||
|
|||
void OnNotifyCollectionChanged(object sender, NotifyCollectionChangedEventArgs args) |
|||
{ |
|||
if (ShouldNotifyListeners(args) && TryGetHandlersForTarget(sender, out var handlers)) |
|||
{ |
|||
handlers(sender, EventArgs.Empty); |
|||
} |
|||
} |
|||
|
|||
bool ShouldNotifyListeners(NotifyCollectionChangedEventArgs e) |
|||
{ |
|||
switch (e.Action) |
|||
{ |
|||
case NotifyCollectionChangedAction.Add: |
|||
return _index >= e.NewStartingIndex; |
|||
case NotifyCollectionChangedAction.Remove: |
|||
return _index >= e.OldStartingIndex; |
|||
case NotifyCollectionChangedAction.Replace: |
|||
return _index >= e.NewStartingIndex && |
|||
_index < e.NewStartingIndex + e.NewItems.Count; |
|||
case NotifyCollectionChangedAction.Move: |
|||
return (_index >= e.NewStartingIndex && |
|||
_index < e.NewStartingIndex + e.NewItems.Count) || |
|||
(_index >= e.OldStartingIndex && |
|||
_index < e.OldStartingIndex + e.OldItems.Count); |
|||
case NotifyCollectionChangedAction.Reset: |
|||
return true; |
|||
} |
|||
return false; |
|||
} |
|||
|
|||
protected override bool ValidateTargetType(object target) |
|||
=> base.ValidateTargetType(target) || target is INotifyCollectionChanged; |
|||
} |
|||
} |
|||
@ -0,0 +1,230 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Collections.Specialized; |
|||
using System.ComponentModel; |
|||
using System.Text; |
|||
using Avalonia.Data; |
|||
using Avalonia.Data.Core; |
|||
using Avalonia.Data.Core.Plugins; |
|||
using Avalonia.Utilities; |
|||
|
|||
namespace Avalonia.Markup.Xaml.MarkupExtensions.CompiledBindings |
|||
{ |
|||
public static class PropertyInfoAccessorFactory |
|||
{ |
|||
public static IPropertyAccessor CreateInpcPropertyAccessor(WeakReference target, IPropertyInfo property) |
|||
=> new InpcPropertyAccessor(target, property); |
|||
|
|||
public static IPropertyAccessor CreateAvaloniaPropertyAccessor(WeakReference target, IPropertyInfo property) |
|||
=> new AvaloniaPropertyAccessor(new WeakReference<AvaloniaObject>((AvaloniaObject)target.Target), (AvaloniaProperty)property); |
|||
|
|||
public static IPropertyAccessor CreateIndexerPropertyAccessor(WeakReference target, IPropertyInfo property, int argument) |
|||
=> new IndexerAccessor(target, property, argument); |
|||
} |
|||
|
|||
internal class AvaloniaPropertyAccessor : PropertyAccessorBase |
|||
{ |
|||
private readonly WeakReference<AvaloniaObject> _reference; |
|||
private readonly AvaloniaProperty _property; |
|||
private IDisposable _subscription; |
|||
|
|||
public AvaloniaPropertyAccessor(WeakReference<AvaloniaObject> reference, AvaloniaProperty property) |
|||
{ |
|||
Contract.Requires<ArgumentNullException>(reference != null); |
|||
Contract.Requires<ArgumentNullException>(property != null); |
|||
|
|||
_reference = reference; |
|||
_property = property; |
|||
} |
|||
|
|||
public AvaloniaObject Instance |
|||
{ |
|||
get |
|||
{ |
|||
_reference.TryGetTarget(out var result); |
|||
return result; |
|||
} |
|||
} |
|||
|
|||
public override Type PropertyType => _property.PropertyType; |
|||
public override object Value => Instance?.GetValue(_property); |
|||
|
|||
public override bool SetValue(object value, BindingPriority priority) |
|||
{ |
|||
if (!_property.IsReadOnly) |
|||
{ |
|||
Instance.SetValue(_property, value, priority); |
|||
return true; |
|||
} |
|||
|
|||
return false; |
|||
} |
|||
|
|||
protected override void SubscribeCore() |
|||
{ |
|||
_subscription = Instance?.GetObservable(_property).Subscribe(PublishValue); |
|||
} |
|||
|
|||
protected override void UnsubscribeCore() |
|||
{ |
|||
_subscription?.Dispose(); |
|||
_subscription = null; |
|||
} |
|||
} |
|||
|
|||
internal class InpcPropertyAccessor : PropertyAccessorBase |
|||
{ |
|||
protected readonly WeakReference _reference; |
|||
private readonly IPropertyInfo _property; |
|||
|
|||
public InpcPropertyAccessor(WeakReference reference, IPropertyInfo property) |
|||
{ |
|||
Contract.Requires<ArgumentNullException>(reference != null); |
|||
Contract.Requires<ArgumentNullException>(property != null); |
|||
|
|||
_reference = reference; |
|||
_property = property; |
|||
} |
|||
|
|||
public override Type PropertyType => _property.PropertyType; |
|||
|
|||
public override object Value |
|||
{ |
|||
get |
|||
{ |
|||
var o = _reference.Target; |
|||
return (o != null) ? _property.Get(o) : null; |
|||
} |
|||
} |
|||
|
|||
public override bool SetValue(object value, BindingPriority priority) |
|||
{ |
|||
if (_property.CanSet && _reference.IsAlive) |
|||
{ |
|||
_property.Set(_reference.Target, value); |
|||
|
|||
SendCurrentValue(); |
|||
|
|||
return true; |
|||
} |
|||
|
|||
return false; |
|||
} |
|||
|
|||
void OnNotifyPropertyChanged(object sender, PropertyChangedEventArgs e) |
|||
{ |
|||
if (e.PropertyName == _property.Name || string.IsNullOrEmpty(e.PropertyName)) |
|||
{ |
|||
SendCurrentValue(); |
|||
} |
|||
} |
|||
|
|||
protected override void SubscribeCore() |
|||
{ |
|||
SendCurrentValue(); |
|||
SubscribeToChanges(); |
|||
} |
|||
|
|||
protected override void UnsubscribeCore() |
|||
{ |
|||
var inpc = _reference.Target as INotifyPropertyChanged; |
|||
|
|||
if (inpc != null) |
|||
{ |
|||
WeakEventHandlerManager.Unsubscribe<PropertyChangedEventArgs, InpcPropertyAccessor>( |
|||
inpc, |
|||
nameof(INotifyPropertyChanged.PropertyChanged), |
|||
OnNotifyPropertyChanged); |
|||
} |
|||
} |
|||
|
|||
protected void SendCurrentValue() |
|||
{ |
|||
try |
|||
{ |
|||
var value = Value; |
|||
PublishValue(value); |
|||
} |
|||
catch { } |
|||
} |
|||
|
|||
private void SubscribeToChanges() |
|||
{ |
|||
var inpc = _reference.Target as INotifyPropertyChanged; |
|||
|
|||
if (inpc != null) |
|||
{ |
|||
WeakEventHandlerManager.Subscribe<INotifyPropertyChanged, PropertyChangedEventArgs, InpcPropertyAccessor>( |
|||
inpc, |
|||
nameof(INotifyPropertyChanged.PropertyChanged), |
|||
OnNotifyPropertyChanged); |
|||
} |
|||
} |
|||
} |
|||
|
|||
internal class IndexerAccessor : InpcPropertyAccessor |
|||
{ |
|||
private int _index; |
|||
|
|||
public IndexerAccessor(WeakReference target, IPropertyInfo basePropertyInfo, int argument) |
|||
:base(target, basePropertyInfo) |
|||
{ |
|||
_index = argument; |
|||
} |
|||
|
|||
|
|||
protected override void SubscribeCore() |
|||
{ |
|||
base.SubscribeCore(); |
|||
if (_reference.Target is INotifyCollectionChanged incc) |
|||
{ |
|||
WeakEventHandlerManager.Subscribe<INotifyCollectionChanged, NotifyCollectionChangedEventArgs, IndexerAccessor>( |
|||
incc, |
|||
nameof(INotifyCollectionChanged.CollectionChanged), |
|||
OnNotifyCollectionChanged); |
|||
} |
|||
} |
|||
|
|||
protected override void UnsubscribeCore() |
|||
{ |
|||
base.UnsubscribeCore(); |
|||
if (_reference.Target is INotifyCollectionChanged incc) |
|||
{ |
|||
WeakEventHandlerManager.Unsubscribe<NotifyCollectionChangedEventArgs, IndexerAccessor>( |
|||
incc, |
|||
nameof(INotifyCollectionChanged.CollectionChanged), |
|||
OnNotifyCollectionChanged); |
|||
} |
|||
} |
|||
|
|||
void OnNotifyCollectionChanged(object sender, NotifyCollectionChangedEventArgs args) |
|||
{ |
|||
if (ShouldNotifyListeners(args)) |
|||
{ |
|||
SendCurrentValue(); |
|||
} |
|||
} |
|||
|
|||
bool ShouldNotifyListeners(NotifyCollectionChangedEventArgs e) |
|||
{ |
|||
switch (e.Action) |
|||
{ |
|||
case NotifyCollectionChangedAction.Add: |
|||
return _index >= e.NewStartingIndex; |
|||
case NotifyCollectionChangedAction.Remove: |
|||
return _index >= e.OldStartingIndex; |
|||
case NotifyCollectionChangedAction.Replace: |
|||
return _index >= e.NewStartingIndex && |
|||
_index < e.NewStartingIndex + e.NewItems.Count; |
|||
case NotifyCollectionChangedAction.Move: |
|||
return (_index >= e.NewStartingIndex && |
|||
_index < e.NewStartingIndex + e.NewItems.Count) || |
|||
(_index >= e.OldStartingIndex && |
|||
_index < e.OldStartingIndex + e.OldItems.Count); |
|||
case NotifyCollectionChangedAction.Reset: |
|||
return true; |
|||
} |
|||
return false; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,103 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using System.Text; |
|||
using Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers; |
|||
using XamlIl.Ast; |
|||
using XamlIl.Transform; |
|||
using XamlIl.TypeSystem; |
|||
|
|||
namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions |
|||
{ |
|||
class XamlIlPropertyInfoAccessorFactoryEmitter |
|||
{ |
|||
private bool _indexerClosureTypeInitialized = false; |
|||
private readonly IXamlIlTypeBuilder _indexerClosureType; |
|||
public XamlIlPropertyInfoAccessorFactoryEmitter(IXamlIlTypeBuilder indexerClosureType) |
|||
{ |
|||
_indexerClosureType = indexerClosureType; |
|||
} |
|||
|
|||
public IXamlIlType EmitLoadInpcPropertyAccessorFactory(XamlIlEmitContext context, IXamlIlEmitter codeGen) |
|||
{ |
|||
codeGen.Ldnull(); |
|||
EmitLoadPropertyAccessorFactory(context, codeGen, context.GetAvaloniaTypes().PropertyInfoAccessorFactory, "CreateInpcPropertyAccessor"); |
|||
return EmitCreateAccessorFactoryDelegate(context, codeGen); |
|||
} |
|||
|
|||
public IXamlIlType EmitLoadAvaloniaPropertyAccessorFactory(XamlIlEmitContext context, IXamlIlEmitter codeGen) |
|||
{ |
|||
codeGen.Ldnull(); |
|||
EmitLoadPropertyAccessorFactory(context, codeGen, context.GetAvaloniaTypes().PropertyInfoAccessorFactory, "CreateAvaloniaPropertyAccessor"); |
|||
return EmitCreateAccessorFactoryDelegate(context, codeGen); |
|||
} |
|||
|
|||
private void EmitLoadPropertyAccessorFactory(XamlIlEmitContext context, IXamlIlEmitter codeGen, IXamlIlType type, string accessorFactoryName) |
|||
{ |
|||
var types = context.GetAvaloniaTypes(); |
|||
var weakReferenceType = context.Configuration.TypeSystem.GetType("System.WeakReference"); |
|||
FindMethodMethodSignature accessorFactorySignature = new FindMethodMethodSignature(accessorFactoryName, types.IPropertyAccessor, weakReferenceType, types.IPropertyInfo) |
|||
{ |
|||
IsStatic = true |
|||
}; |
|||
codeGen.Ldftn(type.GetMethod(accessorFactorySignature)); |
|||
} |
|||
|
|||
public IXamlIlType EmitLoadIndexerAccessorFactory(XamlIlEmitContext context, IXamlIlEmitter codeGen, IXamlIlAstValueNode value) |
|||
{ |
|||
const string indexerClosureFactoryMethodName = "CreateAccessor"; |
|||
var types = context.GetAvaloniaTypes(); |
|||
var intType = context.Configuration.TypeSystem.GetType("System.Int32"); |
|||
var weakReferenceType = context.Configuration.TypeSystem.GetType("System.WeakReference"); |
|||
if (!_indexerClosureTypeInitialized) |
|||
{ |
|||
var indexAccessorFactoryMethod = context.GetAvaloniaTypes().PropertyInfoAccessorFactory.GetMethod( |
|||
new FindMethodMethodSignature( |
|||
"CreateIndexerPropertyAccessor", |
|||
types.IPropertyAccessor, |
|||
weakReferenceType, |
|||
types.IPropertyInfo, |
|||
intType) |
|||
{ |
|||
IsStatic = true |
|||
}); |
|||
var indexField = _indexerClosureType.DefineField(intType, "_index", false, false); |
|||
var ctor = _indexerClosureType.DefineConstructor(false, intType); |
|||
ctor.Generator |
|||
.Ldarg_0() |
|||
.Stfld(indexField); |
|||
_indexerClosureType.DefineMethod( |
|||
types.IPropertyAccessor, |
|||
new[] { weakReferenceType, types.IPropertyInfo }, |
|||
indexerClosureFactoryMethodName, |
|||
isPublic: false, |
|||
isStatic: false, |
|||
isInterfaceImpl: false) |
|||
.Generator |
|||
.Ldarg_0() |
|||
.Ldarg(1) |
|||
.Ldfld(indexField) |
|||
.EmitCall(indexAccessorFactoryMethod); |
|||
} |
|||
|
|||
context.Emit(value, codeGen, intType); |
|||
codeGen.Newobj(_indexerClosureType.FindConstructor(new List<IXamlIlType> { intType })); |
|||
EmitLoadPropertyAccessorFactory(context, codeGen, _indexerClosureType, indexerClosureFactoryMethodName); |
|||
return EmitCreateAccessorFactoryDelegate(context, codeGen); |
|||
} |
|||
|
|||
private IXamlIlType EmitCreateAccessorFactoryDelegate(XamlIlEmitContext context, IXamlIlEmitter codeGen) |
|||
{ |
|||
var types = context.GetAvaloniaTypes(); |
|||
var weakReferenceType = context.Configuration.TypeSystem.GetType("System.WeakReference"); |
|||
var funcType = context.Configuration.TypeSystem.GetType("System.Func`3").MakeGenericType( |
|||
weakReferenceType, |
|||
types.IPropertyInfo, |
|||
types.IPropertyAccessor); |
|||
codeGen.Newobj(funcType.Constructors.First(c => |
|||
c.Parameters.Count == 2 && |
|||
c.Parameters[0].Equals(context.Configuration.WellKnownTypes.Object))); |
|||
return funcType; |
|||
} |
|||
} |
|||
} |
|||
Loading…
Reference in new issue