Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit ec14c65

Browse files
Resolve #48. Add PropertyCastWrappers.
1 parent 3fda705 commit ec14c65

16 files changed

+298
-22
lines changed

‎src/UnityMvvmToolkit.Core/BindingContextObjectProvider.cs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,14 @@ public IProperty<TValueType> RentProperty<TValueType>(IBindingContext context, P
8686
return GetProperty<IProperty<TValueType>, TValueType>(context, bindingData);
8787
}
8888

89+
public IProperty<TValueType> RentPropertyAs<TValueType>(IBindingContext context,
90+
PropertyBindingData bindingData)
91+
{
92+
EnsureBindingDataValid(bindingData);
93+
94+
return GetPropertyAs<IProperty<TValueType>, TValueType>(context, bindingData);
95+
}
96+
8997
public void ReturnProperty<TValueType>(IProperty<TValueType> property)
9098
{
9199
ReturnBaseProperty(property);
@@ -99,6 +107,14 @@ public IReadOnlyProperty<TValueType> RentReadOnlyProperty<TValueType>(IBindingCo
99107
return GetProperty<IReadOnlyProperty<TValueType>, TValueType>(context, bindingData);
100108
}
101109

110+
public IReadOnlyProperty<TValueType> RentReadOnlyPropertyAs<TValueType>(IBindingContext context,
111+
PropertyBindingData bindingData)
112+
{
113+
EnsureBindingDataValid(bindingData);
114+
115+
return GetPropertyAs<IReadOnlyProperty<TValueType>, TValueType>(context, bindingData);
116+
}
117+
102118
public void ReturnReadOnlyProperty<TValueType>(IReadOnlyProperty<TValueType> property)
103119
{
104120
ReturnBaseProperty(property);
@@ -167,6 +183,18 @@ private TProperty GetProperty<TProperty, TValueType>(IBindingContext context, Bi
167183
return _objectWrapperHandler.GetProperty<TProperty, TValueType>(context, bindingData, memberInfo);
168184
}
169185

186+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
187+
private TProperty GetPropertyAs<TProperty, TValueType>(IBindingContext context, BindingData bindingData)
188+
where TProperty : IBaseProperty
189+
{
190+
if (TryGetContextMemberInfo(context.GetType(), bindingData.PropertyName, out var memberInfo) == false)
191+
{
192+
throw new InvalidOperationException($"Property '{bindingData.PropertyName}' not found.");
193+
}
194+
195+
return _objectWrapperHandler.GetPropertyAs<TProperty, TValueType>(context, memberInfo);
196+
}
197+
170198
[MethodImpl(MethodImplOptions.AggressiveInlining)]
171199
private bool TryGetContextMemberInfo(Type contextType, string memberName, out MemberInfo memberInfo)
172200
{

‎src/UnityMvvmToolkit.Core/Interfaces/IObjectProvider.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,13 @@ IObjectProvider WarmupValueConverter<T>(int capacity, WarmupType warmupType = Wa
1515
where T : IValueConverter;
1616

1717
IProperty<TValueType> RentProperty<TValueType>(IBindingContext context, PropertyBindingData bindingData);
18+
IProperty<TValueType> RentPropertyAs<TValueType>(IBindingContext context, PropertyBindingData bindingData);
1819
void ReturnProperty<TValueType>(IProperty<TValueType> property);
1920

2021
IReadOnlyProperty<TValueType> RentReadOnlyProperty<TValueType>(IBindingContext context,
2122
PropertyBindingData bindingData);
22-
23+
IReadOnlyProperty<TValueType> RentReadOnlyPropertyAs<TValueType>(IBindingContext context,
24+
PropertyBindingData bindingData);
2325
void ReturnReadOnlyProperty<TValueType>(IReadOnlyProperty<TValueType> property);
2426

2527
TCommand GetCommand<TCommand>(IBindingContext context, string propertyName) where TCommand : IBaseCommand;

‎src/UnityMvvmToolkit.Core/Internal/ObjectHandlers/ObjectWrapperHandler.cs

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
using System.Collections.Generic;
33
using System.Reflection;
44
using System.Runtime.CompilerServices;
5+
using UnityMvvmToolkit.Core.Converters.PropertyValueConverters;
56
using UnityMvvmToolkit.Core.Enums;
67
using UnityMvvmToolkit.Core.Interfaces;
78
using UnityMvvmToolkit.Core.Internal.Extensions;
@@ -50,6 +51,54 @@ public void CreateValueConverterInstances<T>(int capacity, WarmupType warmupType
5051
}
5152
}
5253

54+
public TProperty GetPropertyAs<TProperty, TValueType>(IBindingContext context, MemberInfo memberInfo)
55+
where TProperty : IBaseProperty
56+
{
57+
var property = GetMemberValue<IBaseProperty>(context, memberInfo, out var propertyType);
58+
59+
var targetType = typeof(TValueType);
60+
var sourceType = propertyType.GenericTypeArguments[0];
61+
62+
if (targetType == sourceType)
63+
{
64+
return (TProperty) property;
65+
}
66+
67+
if (targetType.IsValueType || sourceType.IsValueType)
68+
{
69+
throw new InvalidOperationException(
70+
$"{nameof(GetPropertyAs)} is not supported for value types. Use {typeof(PropertyValueConverter<,>).Name} instead.");
71+
}
72+
73+
if (targetType.IsAssignableFrom(sourceType) == false)
74+
{
75+
throw new InvalidCastException($"Can not cast the '{sourceType}' to the '{targetType}'.");
76+
}
77+
78+
var converterId = HashCodeHelper.GetPropertyWrapperConverterId(targetType, sourceType);
79+
80+
if (_wrappersByConverter.TryGetValue(converterId, out var propertyWrappers))
81+
{
82+
if (propertyWrappers.Count > 0)
83+
{
84+
return (TProperty) propertyWrappers
85+
.Dequeue()
86+
.AsPropertyWrapper()
87+
.SetProperty(property);
88+
}
89+
}
90+
else
91+
{
92+
_wrappersByConverter.Add(converterId, new Queue<IObjectWrapper>());
93+
}
94+
95+
var wrapperType = property is IProperty
96+
? typeof(PropertyCastWrapper<,>).MakeGenericType(sourceType, targetType)
97+
: typeof(ReadOnlyPropertyCastWrapper<,>).MakeGenericType(sourceType, targetType);
98+
99+
return (TProperty) ObjectWrapperHelper.CreatePropertyWrapper(wrapperType, default, converterId, property);
100+
}
101+
53102
public TProperty GetProperty<TProperty, TValueType>(IBindingContext context, BindingData bindingData,
54103
MemberInfo memberInfo) where TProperty : IBaseProperty
55104
{
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
namespace UnityMvvmToolkit.Core.Internal.ObjectWrappers
2+
{
3+
internal sealed class PropertyCastWrapper<TSource, TValue> : PropertyWrapper<TSource, TValue>
4+
{
5+
public PropertyCastWrapper() : base(default)
6+
{
7+
}
8+
9+
protected override TValue Convert(TSource value)
10+
{
11+
return (TValue) (object) value;
12+
}
13+
14+
protected override TSource ConvertBack(TValue value)
15+
{
16+
return (TSource) (object) value;
17+
}
18+
}
19+
}

‎src/UnityMvvmToolkit.Core/Internal/ObjectWrappers/PropertyWrapper.TSource.TValue.cs

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77

88
namespace UnityMvvmToolkit.Core.Internal.ObjectWrappers
99
{
10-
internal sealedclass PropertyWrapper<TSource, TValue> : IProperty<TValue>, IPropertyWrapper
10+
internal class PropertyWrapper<TSource, TValue> : IProperty<TValue>, IPropertyWrapper
1111
{
1212
private readonly IPropertyValueConverter<TSource, TValue> _valueConverter;
1313

@@ -53,14 +53,14 @@ public IPropertyWrapper SetProperty(IBaseProperty property)
5353
if (_property is not null)
5454
{
5555
throw new InvalidOperationException(
56-
$"{nameof(PropertyWrapper<TValue,TSource>)} was not reset.");
56+
$"{nameof(PropertyWrapper<TSource,TValue>)} was not reset.");
5757
}
5858

5959
_property = (IProperty<TSource>) property;
6060
_property.ValueChanged += OnPropertyValueChanged;
6161

6262
_sourceValue = _property.Value;
63-
_value = _valueConverter.Convert(_sourceValue);
63+
_value = Convert(_sourceValue);
6464

6565
return this;
6666
}
@@ -75,7 +75,7 @@ public bool TrySetValue(TValue value)
7575

7676
_value = value;
7777

78-
_sourceValue = _valueConverter.ConvertBack(value);
78+
_sourceValue = ConvertBack(value);
7979
_property.ForceSetValue(_sourceValue);
8080

8181
return true;
@@ -94,15 +94,24 @@ private void OnPropertyValueChanged(object sender, TSource sourceValue)
9494
if (EqualityComparer<TSource>.Default.Equals(_sourceValue, sourceValue) == false)
9595
{
9696
_sourceValue = sourceValue;
97-
_value = _valueConverter.Convert(sourceValue);
97+
_value = Convert(sourceValue);
9898
}
9999

100100
ValueChanged?.Invoke(this, _value);
101101
}
102102

103-
void IProperty<TValue>.ForceSetValue(TValue value)
103+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
104+
protected virtual TValue Convert(TSource value)
105+
{
106+
return _valueConverter.Convert(value);
107+
}
108+
109+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
110+
protected virtual TSource ConvertBack(TValue value)
104111
{
105-
thrownewNotImplementedException();
112+
return_valueConverter.ConvertBack(value);
106113
}
114+
115+
void IProperty<TValue>.ForceSetValue(TValue value) => throw new NotImplementedException();
107116
}
108117
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
namespace UnityMvvmToolkit.Core.Internal.ObjectWrappers
2+
{
3+
internal sealed class ReadOnlyPropertyCastWrapper<TSource, TValue> : ReadOnlyPropertyWrapper<TSource, TValue>
4+
{
5+
public ReadOnlyPropertyCastWrapper() : base(default)
6+
{
7+
}
8+
9+
protected override TValue Convert(TSource value)
10+
{
11+
return (TValue) (object) value;
12+
}
13+
}
14+
}

‎src/UnityMvvmToolkit.Core/Internal/ObjectWrappers/ReadOnlyPropertyWrapper.TSource.TValue.cs

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
namespace UnityMvvmToolkit.Core.Internal.ObjectWrappers
88
{
9-
internal sealedclass ReadOnlyPropertyWrapper<TSource, TValue> : IReadOnlyProperty<TValue>, IPropertyWrapper
9+
internal class ReadOnlyPropertyWrapper<TSource, TValue> : IReadOnlyProperty<TValue>, IPropertyWrapper
1010
{
1111
private readonly IPropertyValueConverter<TSource, TValue> _valueConverter;
1212

@@ -51,10 +51,10 @@ public IPropertyWrapper SetProperty(IBaseProperty readOnlyProperty)
5151
if (_isInitialized)
5252
{
5353
throw new InvalidOperationException(
54-
$"{nameof(ReadOnlyPropertyWrapper<TValue,TSource>)} was not reset.");
54+
$"{nameof(ReadOnlyPropertyWrapper<TSource,TValue>)} was not reset.");
5555
}
5656

57-
_value = _valueConverter.Convert(((IReadOnlyProperty<TSource>) readOnlyProperty).Value);
57+
_value = Convert(((IReadOnlyProperty<TSource>) readOnlyProperty).Value);
5858
_isInitialized = true;
5959

6060
return this;
@@ -65,5 +65,11 @@ public void Reset()
6565
_value = default;
6666
_isInitialized = false;
6767
}
68+
69+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
70+
protected virtual TValue Convert(TSource value)
71+
{
72+
return _valueConverter.Convert(value);
73+
}
6874
}
6975
}

‎src/UnityMvvmToolkit.UnityPackage/Assets/Plugins/UnityMvvmToolkit/Runtime/Core/BindingContextObjectProvider.cs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,14 @@ public IProperty<TValueType> RentProperty<TValueType>(IBindingContext context, P
8686
return GetProperty<IProperty<TValueType>, TValueType>(context, bindingData);
8787
}
8888

89+
public IProperty<TValueType> RentPropertyAs<TValueType>(IBindingContext context,
90+
PropertyBindingData bindingData)
91+
{
92+
EnsureBindingDataValid(bindingData);
93+
94+
return GetPropertyAs<IProperty<TValueType>, TValueType>(context, bindingData);
95+
}
96+
8997
public void ReturnProperty<TValueType>(IProperty<TValueType> property)
9098
{
9199
ReturnBaseProperty(property);
@@ -99,6 +107,14 @@ public IReadOnlyProperty<TValueType> RentReadOnlyProperty<TValueType>(IBindingCo
99107
return GetProperty<IReadOnlyProperty<TValueType>, TValueType>(context, bindingData);
100108
}
101109

110+
public IReadOnlyProperty<TValueType> RentReadOnlyPropertyAs<TValueType>(IBindingContext context,
111+
PropertyBindingData bindingData)
112+
{
113+
EnsureBindingDataValid(bindingData);
114+
115+
return GetPropertyAs<IReadOnlyProperty<TValueType>, TValueType>(context, bindingData);
116+
}
117+
102118
public void ReturnReadOnlyProperty<TValueType>(IReadOnlyProperty<TValueType> property)
103119
{
104120
ReturnBaseProperty(property);
@@ -167,6 +183,18 @@ private TProperty GetProperty<TProperty, TValueType>(IBindingContext context, Bi
167183
return _objectWrapperHandler.GetProperty<TProperty, TValueType>(context, bindingData, memberInfo);
168184
}
169185

186+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
187+
private TProperty GetPropertyAs<TProperty, TValueType>(IBindingContext context, BindingData bindingData)
188+
where TProperty : IBaseProperty
189+
{
190+
if (TryGetContextMemberInfo(context.GetType(), bindingData.PropertyName, out var memberInfo) == false)
191+
{
192+
throw new InvalidOperationException($"Property '{bindingData.PropertyName}' not found.");
193+
}
194+
195+
return _objectWrapperHandler.GetPropertyAs<TProperty, TValueType>(context, memberInfo);
196+
}
197+
170198
[MethodImpl(MethodImplOptions.AggressiveInlining)]
171199
private bool TryGetContextMemberInfo(Type contextType, string memberName, out MemberInfo memberInfo)
172200
{

‎src/UnityMvvmToolkit.UnityPackage/Assets/Plugins/UnityMvvmToolkit/Runtime/Core/Interfaces/IObjectProvider.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,13 @@ IObjectProvider WarmupValueConverter<T>(int capacity, WarmupType warmupType = Wa
1515
where T : IValueConverter;
1616

1717
IProperty<TValueType> RentProperty<TValueType>(IBindingContext context, PropertyBindingData bindingData);
18+
IProperty<TValueType> RentPropertyAs<TValueType>(IBindingContext context, PropertyBindingData bindingData);
1819
void ReturnProperty<TValueType>(IProperty<TValueType> property);
1920

2021
IReadOnlyProperty<TValueType> RentReadOnlyProperty<TValueType>(IBindingContext context,
2122
PropertyBindingData bindingData);
22-
23+
IReadOnlyProperty<TValueType> RentReadOnlyPropertyAs<TValueType>(IBindingContext context,
24+
PropertyBindingData bindingData);
2325
void ReturnReadOnlyProperty<TValueType>(IReadOnlyProperty<TValueType> property);
2426

2527
TCommand GetCommand<TCommand>(IBindingContext context, string propertyName) where TCommand : IBaseCommand;

‎src/UnityMvvmToolkit.UnityPackage/Assets/Plugins/UnityMvvmToolkit/Runtime/Core/Internal/ObjectHandlers/ObjectWrapperHandler.cs

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
using System.Collections.Generic;
33
using System.Reflection;
44
using System.Runtime.CompilerServices;
5+
using UnityMvvmToolkit.Core.Converters.PropertyValueConverters;
56
using UnityMvvmToolkit.Core.Enums;
67
using UnityMvvmToolkit.Core.Interfaces;
78
using UnityMvvmToolkit.Core.Internal.Extensions;
@@ -50,6 +51,54 @@ public void CreateValueConverterInstances<T>(int capacity, WarmupType warmupType
5051
}
5152
}
5253

54+
public TProperty GetPropertyAs<TProperty, TValueType>(IBindingContext context, MemberInfo memberInfo)
55+
where TProperty : IBaseProperty
56+
{
57+
var property = GetMemberValue<IBaseProperty>(context, memberInfo, out var propertyType);
58+
59+
var targetType = typeof(TValueType);
60+
var sourceType = propertyType.GenericTypeArguments[0];
61+
62+
if (targetType == sourceType)
63+
{
64+
return (TProperty) property;
65+
}
66+
67+
if (targetType.IsValueType || sourceType.IsValueType)
68+
{
69+
throw new InvalidOperationException(
70+
$"{nameof(GetPropertyAs)} is not supported for value types. Use {typeof(PropertyValueConverter<,>).Name} instead.");
71+
}
72+
73+
if (targetType.IsAssignableFrom(sourceType) == false)
74+
{
75+
throw new InvalidCastException($"Can not cast the '{sourceType}' to the '{targetType}'.");
76+
}
77+
78+
var converterId = HashCodeHelper.GetPropertyWrapperConverterId(targetType, sourceType);
79+
80+
if (_wrappersByConverter.TryGetValue(converterId, out var propertyWrappers))
81+
{
82+
if (propertyWrappers.Count > 0)
83+
{
84+
return (TProperty) propertyWrappers
85+
.Dequeue()
86+
.AsPropertyWrapper()
87+
.SetProperty(property);
88+
}
89+
}
90+
else
91+
{
92+
_wrappersByConverter.Add(converterId, new Queue<IObjectWrapper>());
93+
}
94+
95+
var wrapperType = property is IProperty
96+
? typeof(PropertyCastWrapper<,>).MakeGenericType(sourceType, targetType)
97+
: typeof(ReadOnlyPropertyCastWrapper<,>).MakeGenericType(sourceType, targetType);
98+
99+
return (TProperty) ObjectWrapperHelper.CreatePropertyWrapper(wrapperType, default, converterId, property);
100+
}
101+
53102
public TProperty GetProperty<TProperty, TValueType>(IBindingContext context, BindingData bindingData,
54103
MemberInfo memberInfo) where TProperty : IBaseProperty
55104
{

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /