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 a1058b4

Browse files
Merge pull request #51 from LibraStack/develop
New functionality.
2 parents 1581099 + d3da804 commit a1058b4

File tree

40 files changed

+880
-167
lines changed

40 files changed

+880
-167
lines changed

‎src/UnityMvvmToolkit.Core/BindingContextObjectProvider.cs

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,13 +79,46 @@ public IObjectProvider WarmupValueConverter<T>(int capacity, WarmupType warmupTy
7979
return this;
8080
}
8181

82+
public bool TryRentProperty<TValueType>(IBindingContext context, PropertyBindingData bindingData,
83+
out IProperty<TValueType> property)
84+
{
85+
EnsureBindingDataValid(bindingData);
86+
87+
if (TryGetContextMemberInfo(context.GetType(), bindingData.PropertyName, out var memberInfo) == false)
88+
{
89+
property = default;
90+
return false;
91+
}
92+
93+
var baseProperty = memberInfo.GetMemberValue<IBaseProperty>(context, out _);
94+
95+
if (baseProperty is IProperty)
96+
{
97+
property = _objectWrapperHandler
98+
.GetProperty<IProperty<TValueType>, TValueType>(context, bindingData, memberInfo);
99+
100+
return true;
101+
}
102+
103+
property = default;
104+
return false;
105+
}
106+
82107
public IProperty<TValueType> RentProperty<TValueType>(IBindingContext context, PropertyBindingData bindingData)
83108
{
84109
EnsureBindingDataValid(bindingData);
85110

86111
return GetProperty<IProperty<TValueType>, TValueType>(context, bindingData);
87112
}
88113

114+
public IProperty<TValueType> RentPropertyAs<TValueType>(IBindingContext context,
115+
PropertyBindingData bindingData)
116+
{
117+
EnsureBindingDataValid(bindingData);
118+
119+
return GetPropertyAs<IProperty<TValueType>, TValueType>(context, bindingData);
120+
}
121+
89122
public void ReturnProperty<TValueType>(IProperty<TValueType> property)
90123
{
91124
ReturnBaseProperty(property);
@@ -99,6 +132,14 @@ public IReadOnlyProperty<TValueType> RentReadOnlyProperty<TValueType>(IBindingCo
99132
return GetProperty<IReadOnlyProperty<TValueType>, TValueType>(context, bindingData);
100133
}
101134

135+
public IReadOnlyProperty<TValueType> RentReadOnlyPropertyAs<TValueType>(IBindingContext context,
136+
PropertyBindingData bindingData)
137+
{
138+
EnsureBindingDataValid(bindingData);
139+
140+
return GetPropertyAs<IReadOnlyProperty<TValueType>, TValueType>(context, bindingData);
141+
}
142+
102143
public void ReturnReadOnlyProperty<TValueType>(IReadOnlyProperty<TValueType> property)
103144
{
104145
ReturnBaseProperty(property);
@@ -167,6 +208,18 @@ private TProperty GetProperty<TProperty, TValueType>(IBindingContext context, Bi
167208
return _objectWrapperHandler.GetProperty<TProperty, TValueType>(context, bindingData, memberInfo);
168209
}
169210

211+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
212+
private TProperty GetPropertyAs<TProperty, TValueType>(IBindingContext context, BindingData bindingData)
213+
where TProperty : IBaseProperty
214+
{
215+
if (TryGetContextMemberInfo(context.GetType(), bindingData.PropertyName, out var memberInfo) == false)
216+
{
217+
throw new InvalidOperationException($"Property '{bindingData.PropertyName}' not found.");
218+
}
219+
220+
return _objectWrapperHandler.GetPropertyAs<TProperty, TValueType>(context, memberInfo);
221+
}
222+
170223
[MethodImpl(MethodImplOptions.AggressiveInlining)]
171224
private bool TryGetContextMemberInfo(Type contextType, string memberName, out MemberInfo memberInfo)
172225
{

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

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,17 @@ public interface IObjectProvider
1414
IObjectProvider WarmupValueConverter<T>(int capacity, WarmupType warmupType = WarmupType.OnlyByType)
1515
where T : IValueConverter;
1616

17+
bool TryRentProperty<TValueType>(IBindingContext context, PropertyBindingData bindingData,
18+
out IProperty<TValueType> property);
19+
1720
IProperty<TValueType> RentProperty<TValueType>(IBindingContext context, PropertyBindingData bindingData);
21+
IProperty<TValueType> RentPropertyAs<TValueType>(IBindingContext context, PropertyBindingData bindingData);
1822
void ReturnProperty<TValueType>(IProperty<TValueType> property);
1923

2024
IReadOnlyProperty<TValueType> RentReadOnlyProperty<TValueType>(IBindingContext context,
2125
PropertyBindingData bindingData);
22-
26+
IReadOnlyProperty<TValueType> RentReadOnlyPropertyAs<TValueType>(IBindingContext context,
27+
PropertyBindingData bindingData);
2328
void ReturnReadOnlyProperty<TValueType>(IReadOnlyProperty<TValueType> property);
2429

2530
TCommand GetCommand<TCommand>(IBindingContext context, string propertyName) where TCommand : IBaseCommand;
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
using System;
2+
using System.Reflection;
3+
using System.Runtime.CompilerServices;
4+
using UnityMvvmToolkit.Core.Interfaces;
5+
6+
namespace UnityMvvmToolkit.Core.Internal.Extensions
7+
{
8+
internal static class MemberInfoExtensions
9+
{
10+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
11+
public static T GetMemberValue<T>(this MemberInfo memberInfo, IBindingContext context, out Type memberType)
12+
{
13+
switch (memberInfo.MemberType)
14+
{
15+
case MemberTypes.Field:
16+
{
17+
var fieldInfo = (FieldInfo) memberInfo;
18+
memberType = fieldInfo.FieldType;
19+
20+
return (T) fieldInfo.GetValue(context);
21+
}
22+
23+
case MemberTypes.Property:
24+
{
25+
var propertyInfo = (PropertyInfo) memberInfo;
26+
memberType = propertyInfo.PropertyType;
27+
28+
return (T) propertyInfo.GetValue(context);
29+
}
30+
31+
default:
32+
throw new ArgumentOutOfRangeException();
33+
}
34+
}
35+
}
36+
}

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

Lines changed: 55 additions & 32 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,10 +51,58 @@ 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 = memberInfo.GetMemberValue<IBaseProperty>(context, 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
{
56-
var property = GetMemberValue<IBaseProperty>(context,memberInfo, out var propertyType);
105+
var property = memberInfo.GetMemberValue<IBaseProperty>(context, out var propertyType);
57106

58107
var targetType = typeof(TValueType);
59108
var sourceType = propertyType.GenericTypeArguments[0];
@@ -90,22 +139,22 @@ public TProperty GetProperty<TProperty, TValueType>(IBindingContext context, Bin
90139
var args = new object[] { valueConverter };
91140

92141
var wrapperType = property is IProperty
93-
? typeof(PropertyWrapper<,>).MakeGenericType(sourceType, targetType)
94-
: typeof(ReadOnlyPropertyWrapper<,>).MakeGenericType(sourceType, targetType);
142+
? typeof(PropertyConvertWrapper<,>).MakeGenericType(sourceType, targetType)
143+
: typeof(ReadOnlyPropertyConvertWrapper<,>).MakeGenericType(sourceType, targetType);
95144

96145
return (TProperty) ObjectWrapperHelper.CreatePropertyWrapper(wrapperType, args, converterId, property);
97146
}
98147

99148
public TCommand GetCommand<TCommand>(IBindingContext context, MemberInfo memberInfo)
100149
where TCommand : IBaseCommand
101150
{
102-
return GetMemberValue<TCommand>(context,memberInfo, out _);
151+
return memberInfo.GetMemberValue<TCommand>(context, out _);
103152
}
104153

105154
public ICommandWrapper GetCommandWrapper(IBindingContext context, CommandBindingData bindingData,
106155
MemberInfo memberInfo)
107156
{
108-
var command = GetMemberValue<IBaseCommand>(context,memberInfo, out var commandType);
157+
var command = memberInfo.GetMemberValue<IBaseCommand>(context, out var commandType);
109158

110159
if (commandType.IsGenericType == false ||
111160
commandType.GetInterface(nameof(IBaseCommand)) == null)
@@ -232,7 +281,7 @@ private void CreatePropertyValueConverterInstances(int converterId, IPropertyVal
232281
var itemsQueue = new Queue<IObjectWrapper>();
233282

234283
var args = new object[] { converter };
235-
var wrapperType = typeof(PropertyWrapper<,>).MakeGenericType(converter.SourceType, converter.TargetType);
284+
var wrapperType = typeof(PropertyConvertWrapper<,>).MakeGenericType(converter.SourceType, converter.TargetType);
236285

237286
for (var i = 0; i < capacity; i++)
238287
{
@@ -304,32 +353,6 @@ private void ReturnWrapper(IObjectWrapper wrapper)
304353
_wrappersByConverter[wrapper.ConverterId].Enqueue(wrapper);
305354
}
306355

307-
[MethodImpl(MethodImplOptions.AggressiveInlining)]
308-
private static T GetMemberValue<T>(IBindingContext context, MemberInfo memberInfo, out Type memberType)
309-
{
310-
switch (memberInfo.MemberType)
311-
{
312-
case MemberTypes.Field:
313-
{
314-
var fieldInfo = (FieldInfo) memberInfo;
315-
memberType = fieldInfo.FieldType;
316-
317-
return (T) fieldInfo.GetValue(context);
318-
}
319-
320-
case MemberTypes.Property:
321-
{
322-
var propertyInfo = (PropertyInfo) memberInfo;
323-
memberType = propertyInfo.PropertyType;
324-
325-
return (T) propertyInfo.GetValue(context);
326-
}
327-
328-
default:
329-
throw new ArgumentOutOfRangeException();
330-
}
331-
}
332-
333356
[MethodImpl(MethodImplOptions.AggressiveInlining)]
334357
private void AssureIsNotDisposed()
335358
{
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
using System.Runtime.CompilerServices;
2+
3+
namespace UnityMvvmToolkit.Core.Internal.ObjectWrappers
4+
{
5+
internal sealed class PropertyCastWrapper<TSource, TValue> : PropertyWrapper<TSource, TValue>
6+
{
7+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
8+
protected override TValue Convert(TSource value)
9+
{
10+
return (TValue) (object) value;
11+
}
12+
13+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
14+
protected override TSource ConvertBack(TValue value)
15+
{
16+
return (TSource) (object) value;
17+
}
18+
}
19+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
using System.Runtime.CompilerServices;
2+
using UnityMvvmToolkit.Core.Attributes;
3+
using UnityMvvmToolkit.Core.Interfaces;
4+
5+
namespace UnityMvvmToolkit.Core.Internal.ObjectWrappers
6+
{
7+
internal sealed class PropertyConvertWrapper<TSource, TValue> : PropertyWrapper<TSource, TValue>
8+
{
9+
private readonly IPropertyValueConverter<TSource, TValue> _valueConverter;
10+
11+
[Preserve]
12+
public PropertyConvertWrapper(IPropertyValueConverter<TSource, TValue> valueConverter)
13+
{
14+
_valueConverter = valueConverter;
15+
}
16+
17+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
18+
protected override TValue Convert(TSource value)
19+
{
20+
return _valueConverter.Convert(value);
21+
}
22+
23+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
24+
protected override TSource ConvertBack(TValue value)
25+
{
26+
return _valueConverter.ConvertBack(value);
27+
}
28+
}
29+
}

0 commit comments

Comments
(0)

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