[Xaml[C]] support op_implicit declared on Target (#585)

This commit is contained in:
Stephane Delcroix 2016-12-07 11:35:32 +01:00 коммит произвёл GitHub
Родитель 8181e6d4cb
Коммит 7851541ab6
4 изменённых файлов: 51 добавлений и 22 удалений

Просмотреть файл

@ -109,6 +109,9 @@ namespace Xamarin.Forms.Build.Tasks
nullableCtor = originalTypeRef.GetMethods(md => md.IsConstructor && md.Parameters.Count == 1, module).Single().Item1;
nullableCtor = nullableCtor.ResolveGenericParameters(nullableTypeRef, module);
}
var implicitOperator = module.TypeSystem.String.GetImplicitOperatorTo(targetTypeRef, module);
//Obvious Built-in conversions
if (targetTypeRef.Resolve().BaseType != null && targetTypeRef.Resolve().BaseType.FullName == "System.Enum")
yield return PushParsedEnum(targetTypeRef, str, node);
@ -203,10 +206,13 @@ namespace Xamarin.Forms.Build.Tasks
context.Body.Method.Module.Import(typeof(decimal))
.Resolve()
.Methods.FirstOrDefault(
md => md.IsConstructor && md.Parameters.Count == 1 && md.Parameters [0].ParameterType.FullName == "System.Int32");
md => md.IsConstructor && md.Parameters.Count == 1 && md.Parameters[0].ParameterType.FullName == "System.Int32");
var decimalctor = context.Body.Method.Module.Import(decimalctorinfo);
yield return Instruction.Create(OpCodes.Newobj, decimalctor);
}
} else if (implicitOperator != null) {
yield return Instruction.Create(OpCodes.Ldstr, node.Value as string);
yield return Instruction.Create(OpCodes.Call, module.Import(implicitOperator));
} else
yield return Instruction.Create(OpCodes.Ldnull);

Просмотреть файл

@ -90,12 +90,12 @@
<local:SV_Foo Value="Bar"/>
</local:MockViewWithValues.BPBar>
</local:MockViewWithValues>
<!--<local:MockViewWithValues x:Name="implicit1" BPFoo="Foo" />-->
<local:MockViewWithValues x:Name="implicit1" BPFoo="Foo" />
<local:MockViewWithValues x:Name="implicit2">
<local:MockViewWithValues.Bar>
<local:SV_Foo Value="Bar"/>
</local:MockViewWithValues.Bar>
</local:MockViewWithValues>
<!--<local:MockViewWithValues x:Name="implicit3" Foo="Foo" />-->
<local:MockViewWithValues x:Name="implicit3" Foo="Foo" />
</StackLayout>
</ContentPage>

Просмотреть файл

@ -311,13 +311,13 @@ namespace Xamarin.Forms.Xaml.UnitTests
Assert.AreEqual("Bar", page.implicit0.GetValue(MockViewWithValues.BPBarProperty));
}
//[TestCase(false)]
//[TestCase(true)]
//public void SetValueWithImplicitOperatorOnTarget(bool useCompiledXaml)
//{
// var page = new SetValue(useCompiledXaml);
// Assert.AreEqual("Foo", ((SV_Foo)page.implicit1.GetValue(MockViewWithValues.BPFooProperty)).Value);
//}
[TestCase(false)]
[TestCase(true)]
public void SetValueWithImplicitOperatorOnTarget(bool useCompiledXaml)
{
var page = new SetValue(useCompiledXaml);
Assert.AreEqual("Foo", ((SV_Foo)page.implicit1.GetValue(MockViewWithValues.BPFooProperty)).Value);
}
[TestCase(false)]
[TestCase(true)]
@ -327,13 +327,13 @@ namespace Xamarin.Forms.Xaml.UnitTests
Assert.AreEqual("Bar", page.implicit2.Bar);
}
//[TestCase(false)]
//[TestCase(true)]
//public void SetWithImplicitOperatorOnTarget(bool useCompiledXaml)
//{
// var page = new SetValue(useCompiledXaml);
// Assert.AreEqual("Foo", page.implicit3.Foo.Value);
//}
[TestCase(false)]
[TestCase(true)]
public void SetWithImplicitOperatorOnTarget(bool useCompiledXaml)
{
var page = new SetValue(useCompiledXaml);
Assert.AreEqual("Foo", page.implicit3.Foo.Value);
}
}
}
}

Просмотреть файл

@ -170,11 +170,34 @@ namespace Xamarin.Forms.Xaml
}
//if there's an implicit conversion, convert
if (value != null)
{
var cast = value.GetType().GetRuntimeMethod("op_Implicit", new[] { value.GetType() });
if (cast != null && cast.ReturnType == toType) {
value = cast.Invoke(null, new [] { value });
if (value != null) {
MethodInfo opImplicit = null;
foreach (var mi in value.GetType().GetRuntimeMethods()) {
if (!mi.IsSpecialName) continue;
if (mi.Name != "op_Implicit") continue;
if (!mi.IsPublic) continue;
if (mi.ReturnType != toType) continue;
var parameters = mi.GetParameters();
if (parameters.Length != 1) continue;
if (parameters[0].ParameterType != value.GetType()) continue;
opImplicit = mi;
break;
}
if (opImplicit == null) {
foreach (var mi in toType.GetRuntimeMethods()) {
if (!mi.IsSpecialName) continue;
if (mi.Name != "op_Implicit") continue;
if (!mi.IsPublic) continue;
if (mi.ReturnType != toType) continue;
var parameters = mi.GetParameters();
if (parameters.Length != 1) continue;
if (parameters[0].ParameterType != value.GetType()) continue;
opImplicit = mi;
break;
}
}
if (opImplicit != null) {
value = opImplicit.Invoke(null, new[] { value });
return value;
}
}