Skip to content

Commit 3097fa1

Browse files
committed
Resolve #27. Fix binding to field commands.
1 parent 27bfbb9 commit 3097fa1

File tree

4 files changed

+64
-52
lines changed

4 files changed

+64
-52
lines changed

src/UnityMvvmToolkit.Core/BindingContextObjectProvider.cs

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -114,15 +114,7 @@ public TCommand GetCommand<TCommand>(IBindingContext context, string propertyNam
114114
throw new InvalidOperationException($"Command '{propertyName}' not found.");
115115
}
116116

117-
var propertyInfo = (PropertyInfo) memberInfo;
118-
119-
if (typeof(TCommand).IsAssignableFrom(propertyInfo.PropertyType))
120-
{
121-
return (TCommand) propertyInfo.GetValue(context);
122-
}
123-
124-
throw new InvalidCastException(
125-
$"Can not cast the {propertyInfo.PropertyType} command to the {typeof(TCommand)} command.");
117+
return _objectWrapperHandler.GetCommand<TCommand>(context, memberInfo);
126118
}
127119

128120
public IBaseCommand RentCommandWrapper(IBindingContext context, CommandBindingData bindingData)

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

Lines changed: 31 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -53,12 +53,14 @@ public void CreateValueConverterInstances<T>(int capacity, WarmupType warmupType
5353
public TProperty GetProperty<TProperty, TValueType>(IBindingContext context, BindingData bindingData,
5454
MemberInfo memberInfo)
5555
{
56+
var property = GetMemberValue(context, memberInfo, out var propertyType);
57+
5658
var targetType = typeof(TValueType);
57-
var contextProperty = GetMemberValue(context, memberInfo, out var sourceType);
59+
var sourceType = propertyType.GenericTypeArguments[0];
5860

59-
if (targetType == sourceType)
61+
if (targetType == sourceType && string.IsNullOrWhiteSpace(bindingData.ConverterName))
6062
{
61-
return (TProperty) contextProperty;
63+
return (TProperty) property;
6264
}
6365

6466
var converterId =
@@ -71,7 +73,7 @@ public TProperty GetProperty<TProperty, TValueType>(IBindingContext context, Bin
7173
return (TProperty) propertyWrappers
7274
.Dequeue()
7375
.AsPropertyWrapper()
74-
.SetProperty(contextProperty);
76+
.SetProperty(property);
7577
}
7678
}
7779
else
@@ -88,24 +90,35 @@ public TProperty GetProperty<TProperty, TValueType>(IBindingContext context, Bin
8890
var args = new object[] { valueConverter };
8991
var wrapperType = typeof(PropertyWrapper<,>).MakeGenericType(sourceType, targetType);
9092

91-
return (TProperty) ObjectWrapperHelper.CreatePropertyWrapper(wrapperType, args, converterId,
92-
contextProperty);
93+
return (TProperty) ObjectWrapperHelper.CreatePropertyWrapper(wrapperType, args, converterId, property);
94+
}
95+
96+
public TCommand GetCommand<TCommand>(IBindingContext context, MemberInfo memberInfo)
97+
{
98+
var command = GetMemberValue(context, memberInfo, out var commandType);
99+
100+
if (typeof(TCommand).IsAssignableFrom(commandType))
101+
{
102+
return (TCommand) command;
103+
}
104+
105+
throw new InvalidCastException(
106+
$"Can not cast the '{commandType}' command to the '{typeof(TCommand)}' command.");
93107
}
94108

95109
public ICommandWrapper GetCommandWrapper(IBindingContext context, CommandBindingData bindingData,
96110
MemberInfo memberInfo)
97111
{
98-
var propertyInfo = (PropertyInfo) memberInfo;
99-
var propertyType = propertyInfo.PropertyType;
112+
var command = GetMemberValue(context, memberInfo, out var commandType);
100113

101-
if (propertyType.IsGenericType == false ||
102-
propertyType.GetInterface(nameof(IBaseCommand)) == null)
114+
if (commandType.IsGenericType == false ||
115+
commandType.GetInterface(nameof(IBaseCommand)) == null)
103116
{
104117
throw new InvalidCastException(
105-
$"Can not cast the {propertyType} command to the {typeof(ICommand<>)} command.");
118+
$"Can not cast the '{commandType}' command to the '{typeof(ICommand<>)}' command.");
106119
}
107120

108-
var commandValueType = propertyType.GenericTypeArguments[0];
121+
var commandValueType = commandType.GenericTypeArguments[0];
109122

110123
var commandId =
111124
HashCodeHelper.GetCommandWrapperId(context.GetType(), commandValueType, bindingData.PropertyName);
@@ -126,7 +139,7 @@ public ICommandWrapper GetCommandWrapper(IBindingContext context, CommandBinding
126139
return commandWrappers
127140
.Dequeue()
128141
.AsCommandWrapper()
129-
.SetCommand(commandId, propertyInfo.GetValue(context))
142+
.SetCommand(commandId, command)
130143
.RegisterParameter(bindingData.ElementId, bindingData.ParameterValue);
131144
}
132145
}
@@ -143,7 +156,6 @@ public ICommandWrapper GetCommandWrapper(IBindingContext context, CommandBinding
143156

144157
var args = new object[] { valueConverter };
145158
var wrapperType = typeof(CommandWrapper<>).MakeGenericType(commandValueType);
146-
var command = propertyInfo.GetValue(context);
147159

148160
commandWrapper = ObjectWrapperHelper
149161
.CreateCommandWrapper(wrapperType, args, converterId, commandId, command)
@@ -297,24 +309,26 @@ private void ReturnWrapper(IObjectWrapper wrapper)
297309
}
298310

299311
[MethodImpl(MethodImplOptions.AggressiveInlining)]
300-
private object GetMemberValue(IBindingContext context, MemberInfo memberInfo, out Type memberValueType)
312+
private static object GetMemberValue(IBindingContext context, MemberInfo memberInfo, out Type memberType)
301313
{
302314
switch (memberInfo.MemberType)
303315
{
304316
case MemberTypes.Field:
305317
{
306318
var fieldInfo = (FieldInfo) memberInfo;
307-
memberValueType = fieldInfo.FieldType.GenericTypeArguments[0];
319+
memberType = fieldInfo.FieldType;
308320

309321
return fieldInfo.GetValue(context);
310322
}
323+
311324
case MemberTypes.Property:
312325
{
313326
var propertyInfo = (PropertyInfo) memberInfo;
314-
memberValueType = propertyInfo.PropertyType.GenericTypeArguments[0];
327+
memberType = propertyInfo.PropertyType;
315328

316329
return propertyInfo.GetValue(context);
317330
}
331+
318332
default:
319333
throw new ArgumentOutOfRangeException();
320334
}

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

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -114,15 +114,7 @@ public TCommand GetCommand<TCommand>(IBindingContext context, string propertyNam
114114
throw new InvalidOperationException($"Command '{propertyName}' not found.");
115115
}
116116

117-
var propertyInfo = (PropertyInfo) memberInfo;
118-
119-
if (typeof(TCommand).IsAssignableFrom(propertyInfo.PropertyType))
120-
{
121-
return (TCommand) propertyInfo.GetValue(context);
122-
}
123-
124-
throw new InvalidCastException(
125-
$"Can not cast the {propertyInfo.PropertyType} command to the {typeof(TCommand)} command.");
117+
return _objectWrapperHandler.GetCommand<TCommand>(context, memberInfo);
126118
}
127119

128120
public IBaseCommand RentCommandWrapper(IBindingContext context, CommandBindingData bindingData)

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

Lines changed: 31 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -53,12 +53,14 @@ public void CreateValueConverterInstances<T>(int capacity, WarmupType warmupType
5353
public TProperty GetProperty<TProperty, TValueType>(IBindingContext context, BindingData bindingData,
5454
MemberInfo memberInfo)
5555
{
56+
var property = GetMemberValue(context, memberInfo, out var propertyType);
57+
5658
var targetType = typeof(TValueType);
57-
var contextProperty = GetMemberValue(context, memberInfo, out var sourceType);
59+
var sourceType = propertyType.GenericTypeArguments[0];
5860

59-
if (targetType == sourceType)
61+
if (targetType == sourceType && string.IsNullOrWhiteSpace(bindingData.ConverterName))
6062
{
61-
return (TProperty) contextProperty;
63+
return (TProperty) property;
6264
}
6365

6466
var converterId =
@@ -71,7 +73,7 @@ public TProperty GetProperty<TProperty, TValueType>(IBindingContext context, Bin
7173
return (TProperty) propertyWrappers
7274
.Dequeue()
7375
.AsPropertyWrapper()
74-
.SetProperty(contextProperty);
76+
.SetProperty(property);
7577
}
7678
}
7779
else
@@ -88,24 +90,35 @@ public TProperty GetProperty<TProperty, TValueType>(IBindingContext context, Bin
8890
var args = new object[] { valueConverter };
8991
var wrapperType = typeof(PropertyWrapper<,>).MakeGenericType(sourceType, targetType);
9092

91-
return (TProperty) ObjectWrapperHelper.CreatePropertyWrapper(wrapperType, args, converterId,
92-
contextProperty);
93+
return (TProperty) ObjectWrapperHelper.CreatePropertyWrapper(wrapperType, args, converterId, property);
94+
}
95+
96+
public TCommand GetCommand<TCommand>(IBindingContext context, MemberInfo memberInfo)
97+
{
98+
var command = GetMemberValue(context, memberInfo, out var commandType);
99+
100+
if (typeof(TCommand).IsAssignableFrom(commandType))
101+
{
102+
return (TCommand) command;
103+
}
104+
105+
throw new InvalidCastException(
106+
$"Can not cast the '{commandType}' command to the '{typeof(TCommand)}' command.");
93107
}
94108

95109
public ICommandWrapper GetCommandWrapper(IBindingContext context, CommandBindingData bindingData,
96110
MemberInfo memberInfo)
97111
{
98-
var propertyInfo = (PropertyInfo) memberInfo;
99-
var propertyType = propertyInfo.PropertyType;
112+
var command = GetMemberValue(context, memberInfo, out var commandType);
100113

101-
if (propertyType.IsGenericType == false ||
102-
propertyType.GetInterface(nameof(IBaseCommand)) == null)
114+
if (commandType.IsGenericType == false ||
115+
commandType.GetInterface(nameof(IBaseCommand)) == null)
103116
{
104117
throw new InvalidCastException(
105-
$"Can not cast the {propertyType} command to the {typeof(ICommand<>)} command.");
118+
$"Can not cast the '{commandType}' command to the '{typeof(ICommand<>)}' command.");
106119
}
107120

108-
var commandValueType = propertyType.GenericTypeArguments[0];
121+
var commandValueType = commandType.GenericTypeArguments[0];
109122

110123
var commandId =
111124
HashCodeHelper.GetCommandWrapperId(context.GetType(), commandValueType, bindingData.PropertyName);
@@ -126,7 +139,7 @@ public ICommandWrapper GetCommandWrapper(IBindingContext context, CommandBinding
126139
return commandWrappers
127140
.Dequeue()
128141
.AsCommandWrapper()
129-
.SetCommand(commandId, propertyInfo.GetValue(context))
142+
.SetCommand(commandId, command)
130143
.RegisterParameter(bindingData.ElementId, bindingData.ParameterValue);
131144
}
132145
}
@@ -143,7 +156,6 @@ public ICommandWrapper GetCommandWrapper(IBindingContext context, CommandBinding
143156

144157
var args = new object[] { valueConverter };
145158
var wrapperType = typeof(CommandWrapper<>).MakeGenericType(commandValueType);
146-
var command = propertyInfo.GetValue(context);
147159

148160
commandWrapper = ObjectWrapperHelper
149161
.CreateCommandWrapper(wrapperType, args, converterId, commandId, command)
@@ -297,24 +309,26 @@ private void ReturnWrapper(IObjectWrapper wrapper)
297309
}
298310

299311
[MethodImpl(MethodImplOptions.AggressiveInlining)]
300-
private object GetMemberValue(IBindingContext context, MemberInfo memberInfo, out Type memberValueType)
312+
private static object GetMemberValue(IBindingContext context, MemberInfo memberInfo, out Type memberType)
301313
{
302314
switch (memberInfo.MemberType)
303315
{
304316
case MemberTypes.Field:
305317
{
306318
var fieldInfo = (FieldInfo) memberInfo;
307-
memberValueType = fieldInfo.FieldType.GenericTypeArguments[0];
319+
memberType = fieldInfo.FieldType;
308320

309321
return fieldInfo.GetValue(context);
310322
}
323+
311324
case MemberTypes.Property:
312325
{
313326
var propertyInfo = (PropertyInfo) memberInfo;
314-
memberValueType = propertyInfo.PropertyType.GenericTypeArguments[0];
327+
memberType = propertyInfo.PropertyType;
315328

316329
return propertyInfo.GetValue(context);
317330
}
331+
318332
default:
319333
throw new ArgumentOutOfRangeException();
320334
}

0 commit comments

Comments
 (0)