Added StyleCop with a ruleset. Formatted code according to rules.

This commit is contained in:
Max Mommersteeg 2018-12-24 11:11:29 +01:00
parent 7176335166
commit e9c9b6041b
76 changed files with 896 additions and 612 deletions

115
StyleCop.ruleset Normal file
View file

@ -0,0 +1,115 @@
<?xml version="1.0" encoding="utf-8"?>
<RuleSet Name="Rules for Qml.Net" Description="Code analysis rules for Qml.Net" ToolsVersion="15.0">
<Rules AnalyzerId="Microsoft.Analyzers.ManagedCodeAnalysis" RuleNamespace="Microsoft.Rules.Managed">
<Rule Id="CA1001" Action="Warning" />
<Rule Id="CA1009" Action="Warning" />
<Rule Id="CA1016" Action="Warning" />
<Rule Id="CA1033" Action="Warning" />
<Rule Id="CA1049" Action="Warning" />
<Rule Id="CA1060" Action="Warning" />
<Rule Id="CA1061" Action="Warning" />
<Rule Id="CA1063" Action="Warning" />
<Rule Id="CA1065" Action="Warning" />
<Rule Id="CA1301" Action="Warning" />
<Rule Id="CA1400" Action="Warning" />
<Rule Id="CA1401" Action="Warning" />
<Rule Id="CA1403" Action="Warning" />
<Rule Id="CA1404" Action="Warning" />
<Rule Id="CA1405" Action="Warning" />
<Rule Id="CA1410" Action="Warning" />
<Rule Id="CA1415" Action="Warning" />
<Rule Id="CA1821" Action="Warning" />
<Rule Id="CA1900" Action="Warning" />
<Rule Id="CA1901" Action="Warning" />
<Rule Id="CA2002" Action="Warning" />
<Rule Id="CA2100" Action="Warning" />
<Rule Id="CA2101" Action="Warning" />
<Rule Id="CA2108" Action="Warning" />
<Rule Id="CA2111" Action="Warning" />
<Rule Id="CA2112" Action="Warning" />
<Rule Id="CA2114" Action="Warning" />
<Rule Id="CA2116" Action="Warning" />
<Rule Id="CA2117" Action="Warning" />
<Rule Id="CA2122" Action="Warning" />
<Rule Id="CA2123" Action="Warning" />
<Rule Id="CA2124" Action="Warning" />
<Rule Id="CA2126" Action="Warning" />
<Rule Id="CA2131" Action="Warning" />
<Rule Id="CA2132" Action="Warning" />
<Rule Id="CA2133" Action="Warning" />
<Rule Id="CA2134" Action="Warning" />
<Rule Id="CA2137" Action="Warning" />
<Rule Id="CA2138" Action="Warning" />
<Rule Id="CA2140" Action="Warning" />
<Rule Id="CA2141" Action="Warning" />
<Rule Id="CA2146" Action="Warning" />
<Rule Id="CA2147" Action="Warning" />
<Rule Id="CA2149" Action="Warning" />
<Rule Id="CA2200" Action="Warning" />
<Rule Id="CA2202" Action="Warning" />
<Rule Id="CA2207" Action="Warning" />
<Rule Id="CA2212" Action="Warning" />
<Rule Id="CA2213" Action="Warning" />
<Rule Id="CA2214" Action="Warning" />
<Rule Id="CA2216" Action="Warning" />
<Rule Id="CA2220" Action="Warning" />
<Rule Id="CA2229" Action="Warning" />
<Rule Id="CA2231" Action="Warning" />
<Rule Id="CA2232" Action="Warning" />
<Rule Id="CA2235" Action="Warning" />
<Rule Id="CA2236" Action="Warning" />
<Rule Id="CA2237" Action="Warning" />
<Rule Id="CA2238" Action="Warning" />
<Rule Id="CA2240" Action="Warning" />
<Rule Id="CA2241" Action="Warning" />
<Rule Id="CA2242" Action="Warning" />
</Rules>
<Rules AnalyzerId="StyleCop.Analyzers" RuleNamespace="StyleCop.Analyzers">
<Rule Id="SA1008" Action="None" />
<Rule Id="SA1009" Action="None" />
<Rule Id="SA1101" Action="None" />
<Rule Id="SA1108" Action="None" />
<Rule Id="SA1118" Action="None" />
<Rule Id="SA1121" Action="None" />
<Rule Id="SA1122" Action="None" />
<Rule Id="SA1129" Action="None" />
<Rule Id="SA1119" Action="None" />
<Rule Id="SA1124" Action="None" />
<Rule Id="SA1200" Action="None" />
<Rule Id="SA1201" Action="None" />
<Rule Id="SA1202" Action="None" />
<Rule Id="SA1204" Action="None" />
<Rule Id="SA1214" Action="None" />
<Rule Id="SA1300" Action="None" />
<Rule Id="SA1304" Action="None" />
<Rule Id="SA1306" Action="None" />
<Rule Id="SA1307" Action="None" />
<Rule Id="SA1309" Action="None" />
<Rule Id="SA1312" Action="None" />
<Rule Id="SA1400" Action="None" />
<Rule Id="SA1401" Action="None" />
<Rule Id="SA1402" Action="None" />
<Rule Id="SA1501" Action="None" />
<Rule Id="SA1503" Action="None" />
<Rule Id="SA1513" Action="None" />
<Rule Id="SA1515" Action="None" />
<Rule Id="SA1520" Action="None" />
<Rule Id="SA1611" Action="None" />
<Rule Id="SA1615" Action="None" />
<Rule Id="SA1633" Action="None" />
<Rule Id="SA1634" Action="None" />
<Rule Id="SA1635" Action="None" />
<Rule Id="SA1636" Action="None" />
<Rule Id="SA1637" Action="None" />
<Rule Id="SA1638" Action="None" />
<Rule Id="SA1640" Action="None" />
<Rule Id="SA1641" Action="None" />
<Rule Id="SA1642" Action="None" />
<Rule Id="SA1643" Action="None" />
<Rule Id="SA1648" Action="None" />
<Rule Id="SA1649" Action="None" />
<Rule Id="SA1652" Action="None" />
<Rule Id="IDE1006" Action="None" />
<Rule Id="SX1101" Action="Warning" />
</Rules>
</RuleSet>

View file

@ -4,7 +4,7 @@ using BenchmarkDotNet.Jobs;
namespace Qml.Net.Benchmarks
{
public class Config: ManualConfig
public class Config : ManualConfig
{
public Config()
{

View file

@ -2,6 +2,7 @@
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp2.1</TargetFramework>
<CodeAnalysisRuleSet>../../../StyleCop.ruleset</CodeAnalysisRuleSet>
<IsPackable>false</IsPackable>
</PropertyGroup>
<ItemGroup>
@ -9,5 +10,9 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="BenchmarkDotNet" Version="0.11.3" />
<PackageReference Include="StyleCop.Analyzers" Version="1.0.2">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
</ItemGroup>
</Project>

View file

@ -18,11 +18,11 @@ namespace Qml.Net.Benchmarks
_initialized = true;
}
}
[IterationSetup]
public void Setup()
{
_guiApplication = new QGuiApplication(new[]{"-platform", "offscreen"});
_guiApplication = new QGuiApplication(new[] { "-platform", "offscreen" });
_qmlApplicationEngine = new QQmlApplicationEngine();
}
@ -32,7 +32,7 @@ namespace Qml.Net.Benchmarks
_qmlApplicationEngine.Dispose();
_guiApplication.Dispose();
}
[Benchmark]
public void Run()
{
@ -73,7 +73,7 @@ namespace Qml.Net.Benchmarks
public class QmlType
{
private readonly InnerType _object = new InnerType();
public object GetObject()
{
return _object;
@ -83,10 +83,9 @@ namespace Qml.Net.Benchmarks
{
_guiApplication.Exit();
}
public class InnerType
{
}
}
}

View file

@ -12,7 +12,7 @@ namespace Qml.Net.Sandbox
public class TestQmlImport
{
public static TestObject ts = new TestObject();
public TestObject GetObject()
{
return ts;
@ -30,17 +30,17 @@ namespace Qml.Net.Sandbox
static int Main(string[] args)
{
Qt.PutEnv("QV4_MM_AGGRESSIVE_GC", "1");
using (var app = new QGuiApplication(args))
{
using (var engine = new QQmlApplicationEngine())
{
engine.AddImportPath(Path.Combine(Directory.GetCurrentDirectory(), "Qml"));
Qml.RegisterType<TestQmlImport>("test");
engine.Load("main.qml");
return app.Exec();
}
}

View file

@ -2,6 +2,7 @@
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp2.1</TargetFramework>
<CodeAnalysisRuleSet>../../../StyleCop.ruleset</CodeAnalysisRuleSet>
<LangVersion>7.1</LangVersion>
<IsPackable>false</IsPackable>
<RunWorkingDirectory>$(MSBuildProjectDirectory)</RunWorkingDirectory>
@ -15,6 +16,10 @@
<None Include="Program.Tests.cs" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="StyleCop.Analyzers" Version="1.0.2">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
<PackageReference Include="xunit.core" Version="2.4.1" />
<PackageReference Include="xunit.runner.utility" Version="2.4.1" />
</ItemGroup>

View file

@ -11,7 +11,7 @@ namespace Qml.Net.Tests
{
Monitor.Enter(LockObject);
}
public virtual void Dispose()
{
Monitor.Exit(LockObject);

View file

@ -1,12 +1,9 @@
using Qml.Net.Internal;
using System;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using Xunit;
using FluentAssertions;
using System.Threading;
using FluentAssertions;
using Qml.Net.Internal;
using Xunit;
namespace Qml.Net.Tests.Internal
{
@ -21,7 +18,7 @@ namespace Qml.Net.Tests.Internal
{
ObjectTagger tagger = new ObjectTagger(10);
List<object> handledObjects = new List<object>();
for(int i=0; i < 9; i++)
for (int i = 0; i < 9; i++)
{
var obj = new object();
tagger.GetOrCreateTag(obj);
@ -42,15 +39,16 @@ namespace Qml.Net.Tests.Internal
tagger.GetOrCreateTag(obj);
handledObjects.Add(obj);
}
//Ids are all used
// Ids are all used.
handledObjects.Clear();
GC.Collect(2, GCCollectionMode.Forced, true);
Thread.Sleep(100);
//the next one is the already prepared next id
// The next one is the already prepared next id.
var obj10 = new object();
var tag10 = tagger.GetOrCreateTag(obj10);
tag10.Should().Be(10ul);
//the next after that will overflow
// The next after that will overflow.
var obj1 = new object();
var tag1 = tagger.GetOrCreateTag(obj1);
tag1.Should().Be(1ul);

View file

@ -10,7 +10,7 @@ namespace Qml.Net.Tests
public MockTypeCreator(params Tuple<Type, object>[] instances)
{
_instances = new Dictionary<Type, object>();
foreach(var tuple in instances)
foreach (var tuple in instances)
{
_instances[tuple.Item1] = tuple.Item2;
}

View file

@ -1,12 +1,17 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp2.1</TargetFramework>
<CodeAnalysisRuleSet>../../../StyleCop.ruleset</CodeAnalysisRuleSet>
<IsPackable>false</IsPackable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="FluentAssertions" Version="5.5.3" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.9.0" />
<PackageReference Include="Moq" Version="4.10.1" />
<PackageReference Include="StyleCop.Analyzers" Version="1.0.2">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
<PackageReference Include="xunit" Version="2.4.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.1" />
<DotNetCliToolReference Include="dotnet-xunit" Version="2.3.1" />

View file

@ -15,20 +15,18 @@ namespace Qml.Net.Tests.Qml
{
return Task.CompletedTask;
}
public virtual Task<string> TestAsyncWithResult()
{
return Task.FromResult("");
return Task.FromResult(string.Empty);
}
public virtual void TestMethod()
{
}
public virtual void TestMethodWithArg(string arg)
{
}
}
@ -59,7 +57,7 @@ namespace Qml.Net.Tests.Qml
SynchronizationContext.SetSynchronizationContext(oldContext);
}
}
[Fact]
public void Can_await_on_task_with_result()
{

View file

@ -31,6 +31,7 @@ namespace Qml.Net.Tests.Qml
{
private readonly QGuiApplication _coreApplication;
protected readonly QQmlApplicationEngine qmlApplicationEngine;
protected MockTypeCreator TypeCreator { get; private set; }
readonly List<Type> _registeredTypes = new List<Type>();
@ -38,7 +39,7 @@ namespace Qml.Net.Tests.Qml
protected AbstractBaseQmlTests()
{
_coreApplication = new QGuiApplication(new []{ "-platform", "offscreen" });
_coreApplication = new QGuiApplication(new[] { "-platform", "offscreen" });
qmlApplicationEngine = new QQmlApplicationEngine();
TypeCreator = new MockTypeCreator();
Net.TypeCreator.Current = TypeCreator;
@ -61,10 +62,11 @@ namespace Qml.Net.Tests.Qml
{
CancellationTokenSource cts = new CancellationTokenSource();
CancellationToken ct = cts.Token;
Task.Factory.StartNew(() =>
Task.Factory.StartNew(
() =>
{
Thread.Sleep(timeoutMs);
if(!ct.IsCancellationRequested)
if (!ct.IsCancellationRequested)
{
_coreApplication.Exit(-1);
}
@ -77,18 +79,20 @@ namespace Qml.Net.Tests.Qml
protected void RunQmlTest(string instanceId, string componentOnCompletedCode)
{
NetTestHelper.RunQml(qmlApplicationEngine,
string.Format(@"
import QtQuick 2.0
import tests 1.0
{0} {{
id: {1}
Component.onCompleted: function() {{
{2}
NetTestHelper.RunQml(
qmlApplicationEngine,
string.Format(
@"
import QtQuick 2.0
import tests 1.0
{0} {{
id: {1}
Component.onCompleted: function() {{
{2}
}}
}}
}}
",
typeof(TTypeToRegister).Name,
",
typeof(TTypeToRegister).Name,
instanceId,
componentOnCompletedCode));
}
@ -104,7 +108,8 @@ namespace Qml.Net.Tests.Qml
}
}
public abstract class BaseQmlTests<T> : AbstractBaseQmlTests<T> where T:class
public abstract class BaseQmlTests<T> : AbstractBaseQmlTests<T>
where T : class
{
protected readonly Mock<T> Mock;
@ -116,7 +121,8 @@ namespace Qml.Net.Tests.Qml
}
}
public abstract class BaseQmlTestsWithInstance<T> : AbstractBaseQmlTests<T> where T : class, new()
public abstract class BaseQmlTestsWithInstance<T> : AbstractBaseQmlTests<T>
where T : class, new()
{
protected readonly T Instance;
@ -128,7 +134,8 @@ namespace Qml.Net.Tests.Qml
}
}
public abstract class BaseQmlMvvmTestsWithInstance<T> : AbstractBaseQmlTests<T> where T : class, new()
public abstract class BaseQmlMvvmTestsWithInstance<T> : AbstractBaseQmlTests<T>
where T : class, new()
{
protected readonly T Instance;

View file

@ -11,15 +11,13 @@ namespace Qml.Net.Tests.Qml
public virtual bool Property { get; set; }
public virtual bool? Nullable { get; set; }
public virtual void MethodParameter(bool value)
{
}
public virtual void MethodParameterNullable(bool? value)
{
}
public virtual bool MethodReturn()
@ -36,7 +34,7 @@ namespace Qml.Net.Tests.Qml
@"
test.property = true
");
Mock.VerifySet(x => x.Property = true, Times.Once);
}
@ -81,7 +79,7 @@ namespace Qml.Net.Tests.Qml
Mock.VerifyGet(x => x.Property, Times.Once);
Mock.Verify(x => x.MethodParameter(It.Is<bool>(y => y)));
}
[Fact]
public void Can_read_nullable_bool_no_value()
{
@ -97,7 +95,7 @@ namespace Qml.Net.Tests.Qml
Mock.VerifyGet(x => x.Nullable, Times.Once);
Mock.Verify(x => x.MethodParameterNullable(It.Is<bool?>(y => y == null)), Times.Once);
}
[Fact]
public void Can_read_nullable_bool_with_value()
{

View file

@ -11,15 +11,13 @@ namespace Qml.Net.Tests.Qml
public virtual char Property { get; set; }
public virtual char? Nullable { get; set; }
public virtual void MethodParameter(char value)
{
}
public virtual void MethodParameterNullable(char? value)
{
}
public virtual char MethodReturn()
@ -27,12 +25,12 @@ namespace Qml.Net.Tests.Qml
return char.MinValue;
}
}
[Fact]
public void Can_read_write_char_null()
{
Mock.Setup(x => x.Property).Returns((char)0);
RunQmlTest(
"test",
@"
@ -98,7 +96,7 @@ namespace Qml.Net.Tests.Qml
Mock.Verify(x => x.MethodParameter(It.IsIn('Ώ')), Times.Once);
}
[Fact]
public void Can_read_nullable_char_no_value()
{
@ -114,7 +112,7 @@ namespace Qml.Net.Tests.Qml
Mock.VerifyGet(x => x.Nullable, Times.Once);
Mock.Verify(x => x.MethodParameterNullable(It.Is<char?>(y => y == null)), Times.Once);
}
[Fact]
public void Can_read_nullable_char_with_value()
{

View file

@ -15,12 +15,10 @@ namespace Qml.Net.Tests.Qml
public virtual void Method(DateTimeOffset value)
{
}
public virtual void MethodNullable(DateTimeOffset? value)
{
}
}
@ -28,7 +26,7 @@ namespace Qml.Net.Tests.Qml
public void Can_read_write_property()
{
var value = DateTimeOffset.Now;
// This trims some percision off of the milliseconds, makes the comparison accurate.
// This trims some precision off of the milliseconds, makes the comparison accurate.
value = new DateTimeOffset(value.Year, value.Month, value.Day, value.Hour, value.Minute, value.Second, value.Millisecond, value.Offset);
Mock.SetupGet(x => x.Property).Returns(value);
Mock.SetupSet(x => x.Property = value);
@ -42,7 +40,7 @@ namespace Qml.Net.Tests.Qml
Mock.VerifyGet(x => x.Property, Times.Once);
Mock.VerifySet(x => x.Property = value, Times.Once);
}
[Fact]
public void Can_read_write_property_nullable_with_value()
{
@ -62,7 +60,7 @@ namespace Qml.Net.Tests.Qml
Mock.VerifyGet(x => x.Nullable, Times.Once);
Mock.VerifySet(x => x.Nullable = value);
}
[Fact]
public void Can_read_write_property_nullable_without_value()
{

View file

@ -1,5 +1,4 @@
using Qml.Net.Internal.Qml;
using System;
using System;
using Moq;
using Xunit;
@ -30,7 +29,7 @@ namespace Qml.Net.Tests.Qml
Mock.VerifyGet(x => x.Property, Times.Once);
Mock.VerifySet(x => x.Property = value, Times.Once);
}
[Fact]
public void Can_read_write_property_nullable_with_value()
{
@ -48,7 +47,7 @@ namespace Qml.Net.Tests.Qml
Mock.VerifyGet(x => x.Nullable, Times.Once);
Mock.VerifySet(x => x.Nullable = value);
}
[Fact]
public void Can_read_write_property_nullable_without_value()
{

View file

@ -12,7 +12,6 @@ namespace Qml.Net.Tests.Qml
public virtual void MethodParameter(double value)
{
}
public virtual double MethodReturn()
@ -20,12 +19,12 @@ namespace Qml.Net.Tests.Qml
return 0;
}
}
[Fact]
public void Can_read_write_int_min_value()
{
Mock.Setup(x => x.Property).Returns(double.MinValue);
RunQmlTest(
"test",
@"

View file

@ -12,7 +12,6 @@ namespace Qml.Net.Tests.Qml
public virtual void MethodParameter(int value)
{
}
public virtual int MethodReturn()
@ -20,12 +19,12 @@ namespace Qml.Net.Tests.Qml
return 0;
}
}
[Fact]
public void Can_read_write_int_min_value()
{
Mock.Setup(x => x.Property).Returns(int.MinValue);
RunQmlTest(
"test",
@"

View file

@ -1,12 +1,9 @@
using System;
using System.Collections.Generic;
using FluentAssertions;
using FluentAssertions.Common;
using Microsoft.VisualStudio.TestPlatform.ObjectModel;
using Moq;
using Qml.Net.Internal.Qml;
using Xunit;
using Qml.Net.Extensions;
using Xunit;
namespace Qml.Net.Tests.Qml
{
@ -16,24 +13,20 @@ namespace Qml.Net.Tests.Qml
{
public virtual void Method(dynamic value)
{
}
public virtual void Method(dynamic value1, dynamic value2)
{
}
public virtual void MethodWithoutParams()
{
}
public virtual void MethodWithParameters(string param1, int param2)
{
}
public virtual void CallMethodWithJsValue(INetJsValue value, INetJsValue method)
{
method.Call(value);
@ -43,11 +36,11 @@ namespace Qml.Net.Tests.Qml
{
return null;
}
public class TestObject
{
public int CalledCount { get; set; }
public void TestMethod()
{
CalledCount++;
@ -61,7 +54,7 @@ namespace Qml.Net.Tests.Qml
INetJsValue jsValue = null;
Mock.Setup(x => x.Method(It.IsAny<INetJsValue>()))
.Callback(new Action<dynamic>(x => jsValue = x));
RunQmlTest(
"test",
@"
@ -72,7 +65,7 @@ namespace Qml.Net.Tests.Qml
jsValue.Should().NotBeNull();
jsValue.IsCallable.Should().BeTrue();
}
[Fact]
public void Can_send_non_function()
{
@ -82,7 +75,7 @@ namespace Qml.Net.Tests.Qml
{
jsValue = x;
}));
RunQmlTest(
"test",
@"
@ -104,7 +97,7 @@ namespace Qml.Net.Tests.Qml
result = x();
}));
Mock.Setup(x => x.MethodWithoutParams());
RunQmlTest(
"test",
@"
@ -128,7 +121,7 @@ namespace Qml.Net.Tests.Qml
result = x("test1", 4);
}));
Mock.Setup(x => x.MethodWithParameters("test1", 4));
RunQmlTest(
"test",
@"
@ -151,7 +144,7 @@ namespace Qml.Net.Tests.Qml
{
x(testObject);
}));
RunQmlTest(
"test",
@"
@ -164,13 +157,13 @@ namespace Qml.Net.Tests.Qml
Mock.Verify(x => x.Method(It.IsAny<INetJsValue>()), Times.Once);
testObject.CalledCount.Should().Be(2);
}
[Fact]
public void Can_pass_js_value_to_callback()
{
Mock.CallBase = true;
Mock.Setup(x => x.MethodWithParameters("test1", 4));
RunQmlTest(
"test",
@"
@ -198,7 +191,7 @@ namespace Qml.Net.Tests.Qml
{
results.Add((object)jsValue());
}));
RunQmlTest(
"test",
@"
@ -242,7 +235,7 @@ namespace Qml.Net.Tests.Qml
result = jsValue;
}));
Mock.Setup(x => x.GetTestObject()).Returns(testObject);
RunQmlTest(
"test",
@"
@ -259,11 +252,11 @@ namespace Qml.Net.Tests.Qml
Mock.Verify(x => x.Method(It.IsAny<INetJsValue>()), Times.Exactly(1));
Mock.Verify(x => x.GetTestObject(), Times.Exactly(1));
((object) result.nonExistant).Should().BeNull();
((int) result.test1).Should().Be(34);
((string) result.test2).Should().Be("test3");
((object)result.nonExistant).Should().BeNull();
((int)result.test1).Should().Be(34);
((string)result.test2).Should().Be("test3");
((object)result.test3).Should().BeSameAs(testObject);
((string) result.test4.test5).Should().Be("test5");
((string)result.test4.test5).Should().Be("test5");
}
[Fact]
@ -282,7 +275,7 @@ namespace Qml.Net.Tests.Qml
}));
Mock.Setup(x => x.Method(It.IsAny<INetJsValue>()))
.Callback(new Action<dynamic>(value => { result = value; }));
RunQmlTest(
"test",
@"
@ -303,11 +296,11 @@ namespace Qml.Net.Tests.Qml
Mock.Verify(x => x.Method(It.IsAny<INetJsValue>()), Times.Exactly(1));
Mock.Verify(x => x.Method(It.IsAny<INetJsValue>(), It.IsAny<INetJsValue>()), Times.Exactly(1));
Mock.Verify(x => x.GetTestObject(), Times.Exactly(1));
((object) result).Should().NotBeNull();
((int) result.dest1).Should().Be(123);
((string) result.dest2).Should().Be("value");
((object) result.dest3).Should().BeSameAs(testObject);
((object) result.dest4).Should().BeAssignableTo<INetJsValue>();
((object)result).Should().NotBeNull();
((int)result.dest1).Should().Be(123);
((string)result.dest2).Should().Be("value");
((object)result.dest3).Should().BeSameAs(testObject);
((object)result.dest4).Should().BeAssignableTo<INetJsValue>();
}
[Fact]
@ -316,9 +309,9 @@ namespace Qml.Net.Tests.Qml
List<string> result = null;
Mock.Setup(x => x.Method(It.IsAny<INetJsValue>())).Callback(new Action<dynamic>(param =>
{
result = ((INetJsValue) param).AsList<string>();
result = ((INetJsValue)param).AsList<string>();
}));
RunQmlTest(
"test",
@"
@ -327,23 +320,23 @@ namespace Qml.Net.Tests.Qml
p.push(""test2"")
test.method(p)
");
Mock.Verify(x => x.Method(It.IsAny<INetJsValue>()), Times.Once);
result.Should().NotBeNull();
result.Count.Should().Be(2);
result[0].Should().Be("test1");
result[1].Should().Be("test2");
}
[Fact]
public void Can_convert_array_to_list_int()
{
List<int> result = null;
Mock.Setup(x => x.Method(It.IsAny<INetJsValue>())).Callback(new Action<dynamic>(param =>
{
result = ((INetJsValue) param).AsList<int>();
result = ((INetJsValue)param).AsList<int>();
}));
RunQmlTest(
"test",
@"
@ -352,7 +345,7 @@ namespace Qml.Net.Tests.Qml
p.push(1)
test.method(p)
");
Mock.Verify(x => x.Method(It.IsAny<INetJsValue>()), Times.Once);
result.Should().NotBeNull();
result.Count.Should().Be(2);

View file

@ -6,7 +6,6 @@ using Xunit;
// ReSharper disable AutoPropertyCanBeMadeGetOnly.Global
// ReSharper disable UnusedMember.Global
// ReSharper disable UnusedAutoPropertyAccessor.Global
namespace Qml.Net.Tests.Qml
{
public class LifetimeTests : BaseQmlTestsWithInstance<LifetimeTests.NetInteropTestQml>
@ -29,7 +28,7 @@ namespace Qml.Net.Tests.Qml
}
public SecondLevelType Parameter { get; set; }
public SecondLevelType Parameter2 { get; set; }
private readonly WeakReference<SecondLevelType> _parameterWeakRef;
@ -39,7 +38,7 @@ namespace Qml.Net.Tests.Qml
Parameter = null;
Parameter2 = null;
}
public bool CheckIsParameterAlive()
{
GC.Collect(GC.MaxGeneration);
@ -187,7 +186,7 @@ namespace Qml.Net.Tests.Qml
Assert.True(Instance.TestResult);
}
[Fact()]
[Fact]
public void Can_handle_instance_deref_of_all_refs_in_qml_and_net()
{
qmlApplicationEngine.LoadData(@"

View file

@ -18,7 +18,6 @@ namespace Qml.Net.Tests.Qml
public virtual void Test(object param)
{
}
}
@ -28,7 +27,7 @@ namespace Qml.Net.Tests.Qml
{
Prop = Guid.NewGuid().ToString();
}
public string Prop { get; set; }
}
@ -43,7 +42,8 @@ namespace Qml.Net.Tests.Qml
Mock.Setup(x => x.GetNetObjectList()).Returns(list);
Mock.Setup(x => x.Test(It.IsAny<object>())).Callback(new Action<object>(o => result.Add((TestNetObject)o)));
NetTestHelper.RunQml(qmlApplicationEngine,
NetTestHelper.RunQml(
qmlApplicationEngine,
@"
import QtQuick 2.0
import tests 1.0
@ -66,8 +66,8 @@ namespace Qml.Net.Tests.Qml
}
}
");
Mock.Verify(x => x.GetNetObjectList(),Times.Once);
Mock.Verify(x => x.GetNetObjectList(), Times.Once);
Mock.Verify(x => x.Test(It.IsAny<object>()), Times.Exactly(3));
list.Count.Should().Be(result.Count);
list[0].Prop.Should().Be(result[0].Prop);
@ -81,7 +81,7 @@ namespace Qml.Net.Tests.Qml
var list = new List<TestNetObject>();
list.Add(new TestNetObject());
Mock.Setup(x => x.GetNetObjectList()).Returns(list);
RunQmlTest(
"test",
@"
@ -92,14 +92,14 @@ namespace Qml.Net.Tests.Qml
Mock.Verify(x => x.Test(1), Times.Once);
}
[Fact]
public void Can_get_at()
{
var list = new List<TestNetObject>();
list.Add(new TestNetObject());
Mock.Setup(x => x.GetNetObjectList()).Returns(list);
RunQmlTest(
"test",
@"
@ -110,14 +110,14 @@ namespace Qml.Net.Tests.Qml
Mock.Verify(x => x.Test(list[0]), Times.Once);
}
[Fact]
public void Can_get_at_invalid()
{
var list = new List<TestNetObject>();
list.Add(new TestNetObject());
Mock.Setup(x => x.GetNetObjectList()).Returns(list);
RunQmlTest(
"test",
@"

View file

@ -1,8 +1,7 @@
using System.ComponentModel;
using System.Runtime.CompilerServices;
using Xunit;
using FluentAssertions;
using Qml.Net.Internal.Qml;
using Xunit;
namespace Qml.Net.Tests.Qml
{
@ -34,7 +33,7 @@ namespace Qml.Net.Tests.Qml
{
ViewModel.NotifyOnlyIntProperty = newValue;
}
public void ChangeCustomNotifyOnlyIntPropertyTo(int newValue)
{
ViewModel.CustomNotifyOnlyIntProperty = newValue;
@ -47,13 +46,15 @@ namespace Qml.Net.Tests.Qml
{
public event PropertyChangedEventHandler PropertyChanged;
private string _stringProperty = "";
private string _stringProperty = string.Empty;
public string StringProperty
{
get
{
return _stringProperty;
}
set
{
if (!Equals(value, _stringProperty))
@ -65,6 +66,7 @@ namespace Qml.Net.Tests.Qml
}
private int _intProperty;
public int IntProperty
{
get => _intProperty;
@ -77,8 +79,9 @@ namespace Qml.Net.Tests.Qml
}
}
}
private int _customIntProperty;
[NotifySignal("customIntPropertyChangedSignal")]
public int CustomIntProperty
{
@ -86,6 +89,7 @@ namespace Qml.Net.Tests.Qml
{
return _customIntProperty;
}
set
{
if (!Equals(value, _customIntProperty))
@ -95,8 +99,9 @@ namespace Qml.Net.Tests.Qml
}
}
}
private int _customMvvmStyleIntProperty;
[NotifySignal]
public int CustomMvvmStyleIntProperty
{
@ -104,6 +109,7 @@ namespace Qml.Net.Tests.Qml
{
return _customMvvmStyleIntProperty;
}
set
{
if (!Equals(value, _customMvvmStyleIntProperty))
@ -113,8 +119,9 @@ namespace Qml.Net.Tests.Qml
}
}
}
private int _notifyOnlyIntProperty;
[NotifySignal]
public int NotifyOnlyIntProperty
{
@ -122,6 +129,7 @@ namespace Qml.Net.Tests.Qml
{
return _notifyOnlyIntProperty;
}
set
{
if (!Equals(value, _notifyOnlyIntProperty))
@ -131,8 +139,9 @@ namespace Qml.Net.Tests.Qml
}
}
}
private int _customNotifyOnlyIntProperty;
[NotifySignal("customNotifyIntPropertyChangedSignal")]
public int CustomNotifyOnlyIntProperty
{
@ -140,6 +149,7 @@ namespace Qml.Net.Tests.Qml
{
return _customNotifyOnlyIntProperty;
}
set
{
if (!Equals(value, _customNotifyOnlyIntProperty))
@ -218,7 +228,7 @@ namespace Qml.Net.Tests.Qml
Instance.TestResult.Should().Be(true);
}
[Fact]
public void Does_play_nicely_with_completely_custom_notify_signals()
{
@ -234,7 +244,7 @@ namespace Qml.Net.Tests.Qml
Instance.TestResult.Should().Be(true);
}
[Fact]
public void Does_play_nicely_with_custom_notify_signals()
{
@ -250,7 +260,7 @@ namespace Qml.Net.Tests.Qml
Instance.TestResult.Should().Be(true);
}
[Fact]
public void Does_not_interfer_with_properties_only_using_notify_signals()
{
@ -266,7 +276,7 @@ namespace Qml.Net.Tests.Qml
Instance.TestResult.Should().Be(true);
}
[Fact]
public void Does_not_interfer_with_properties_only_using_custom_notify_signals()
{

View file

@ -10,16 +10,15 @@ namespace Qml.Net.Tests.Qml
{
public class TestObject
{
}
[Fact]
public void Variant_is_invalid_by_default()
{
var variant = new NetVariant();
variant.VariantType.Should().Be(NetVariantType.Invalid);
}
[Fact]
public void Can_store_net_instance()
{
@ -31,7 +30,7 @@ namespace Qml.Net.Tests.Qml
variant.Instance.Instance.Should().Be(testObject);
variant.VariantType.Should().Be(NetVariantType.Object);
}
[Fact]
public void Can_store_bool()
{
@ -42,7 +41,7 @@ namespace Qml.Net.Tests.Qml
variant.Bool = false;
variant.Bool.Should().BeFalse();
}
[Fact]
public void Can_store_char()
{
@ -53,7 +52,7 @@ namespace Qml.Net.Tests.Qml
variant.Char = ' ';
variant.Char.Should().Be(' ');
}
[Fact]
public void Can_store_int()
{
@ -64,7 +63,7 @@ namespace Qml.Net.Tests.Qml
variant.Int = int.MaxValue;
variant.Int.Should().Be(int.MaxValue);
}
[Fact]
public void Can_store_uint()
{
@ -75,7 +74,7 @@ namespace Qml.Net.Tests.Qml
variant.UInt = uint.MaxValue;
variant.UInt.Should().Be(uint.MaxValue);
}
[Fact]
public void Can_store_long()
{
@ -86,7 +85,7 @@ namespace Qml.Net.Tests.Qml
variant.Long = long.MaxValue;
variant.Long.Should().Be(long.MaxValue);
}
[Fact]
public void Can_store_ulong()
{
@ -97,7 +96,7 @@ namespace Qml.Net.Tests.Qml
variant.ULong = ulong.MaxValue;
variant.ULong.Should().Be(ulong.MaxValue);
}
[Fact]
public void Can_store_float()
{
@ -108,7 +107,7 @@ namespace Qml.Net.Tests.Qml
variant.Float = float.MaxValue;
variant.Float.Should().Be(float.MaxValue);
}
[Fact]
public void Can_store_double()
{
@ -119,7 +118,7 @@ namespace Qml.Net.Tests.Qml
variant.Double = double.MaxValue;
variant.Double.Should().Be(double.MaxValue);
}
[Fact]
public void Can_store_string()
{
@ -133,7 +132,7 @@ namespace Qml.Net.Tests.Qml
variant.String = null;
variant.String.Should().BeNull();
}
[Fact]
public void Can_store_date()
{
@ -152,7 +151,7 @@ namespace Qml.Net.Tests.Qml
value.Value.Millisecond.Should().Be(0);
value.Value.Offset.Should().Be(TimeSpan.FromHours(5));
}
[Fact]
public void Can_clear_value()
{

View file

@ -15,25 +15,20 @@ namespace Qml.Net.Tests.Qml
public virtual void TestMethodParameter(ObjectTestsQmlReturnType parameter)
{
}
public virtual void Overload()
{
}
public virtual void Overload(string param)
{
}
public object TestObjectProperty { get; set; }
public virtual void TestObjectPropertyTest(string result)
{
}
}
@ -41,7 +36,6 @@ namespace Qml.Net.Tests.Qml
{
public virtual void TestMethod()
{
}
}
@ -90,16 +84,16 @@ namespace Qml.Net.Tests.Qml
@"
test.overload()
");
Mock.Verify(x => x.Overload(), Times.Once);
Mock.Verify(x => x.Overload(It.IsAny<string>()), Times.Never);
RunQmlTest(
"test",
@"
test.overload('test')
");
Mock.Verify(x => x.Overload(), Times.Once);
Mock.Verify(x => x.Overload(It.IsAny<string>()), Times.Once);
}
@ -108,13 +102,13 @@ namespace Qml.Net.Tests.Qml
public void Can_get_null()
{
Mock.Setup(x => x.TestObjectPropertyTest(It.IsAny<string>()));
RunQmlTest(
"test",
@"
test.testObjectPropertyTest(typeof test.testObjectProperty)
");
Mock.Verify(x => x.TestObjectPropertyTest("object"), Times.Once);
}
}

View file

@ -23,7 +23,7 @@ namespace Qml.Net.Tests.Qml
var o = new QQmlApplicationEngineQml();
o.Guid = Guid.NewGuid();
qmlApplicationEngine.SetContextProperty(propName, o);
((QQmlApplicationEngineQml) qmlApplicationEngine.GetContextProperty(propName)).Guid.Should().Be(o.Guid);
((QQmlApplicationEngineQml)qmlApplicationEngine.GetContextProperty(propName)).Guid.Should().Be(o.Guid);
}
}
}

View file

@ -11,17 +11,17 @@ namespace Qml.Net.Tests.Qml
{
return null;
}
public virtual string Result { get; set; }
}
public class JsonObject
{
public string Prop1 { get; set; }
public int Prop2 { get; set; }
}
[Fact]
public void Can_serialize_object()
{
@ -31,14 +31,14 @@ namespace Qml.Net.Tests.Qml
var jsonObjectSerialized = Serializer.Current.Serialize(jsonObject);
Mock.Setup(x => x.GetJsonObject()).Returns(jsonObject);
Mock.SetupSet(x => x.Result = jsonObjectSerialized);
RunQmlTest(
"test",
@"
var jsonObject = test.getJsonObject()
test.result = Net.serialize(jsonObject)
");
Mock.Verify(x => x.GetJsonObject(), Times.Once);
Mock.VerifySet(x => x.Result = jsonObjectSerialized, Times.Once);
}

View file

@ -19,17 +19,14 @@ namespace Qml.Net.Tests.Qml
public virtual void MethodWithArgs(string arg1, int arg2)
{
}
public virtual void TestMethod()
{
}
public virtual void TestMethodWithArgs(string arg1, int arg2)
{
}
private string _someStringPropertyValue = "";
@ -38,8 +35,9 @@ namespace Qml.Net.Tests.Qml
public string SomeStringProperty
{
get => _someStringPropertyValue;
set {
if (_someStringPropertyValue == value)
set
{
if (_someStringPropertyValue == value)
return;
_someStringPropertyValue = value;
this.ActivateNotifySignal();
@ -47,26 +45,32 @@ namespace Qml.Net.Tests.Qml
}
private int _someIntPropertyValue = 0;
[NotifySignal("someWeirdSignalName")]
public int SomeIntProperty
{
get => _someIntPropertyValue;
set {
if (_someIntPropertyValue == value)
set
{
if (_someIntPropertyValue == value)
return;
_someIntPropertyValue = value;
this.ActivateNotifySignal();
}
}
private bool _someBoolPropertyValue = false;
public bool SomeBoolProperty
{
get => _someBoolPropertyValue;
set {
if (_someBoolPropertyValue == value)
get
{
return _someBoolPropertyValue;
}
set
{
if (_someBoolPropertyValue == value)
return;
_someBoolPropertyValue = value;
this.ActivateNotifySignal();
@ -85,7 +89,6 @@ namespace Qml.Net.Tests.Qml
[Signal("testSignalWithNetArg", NetVariantType.Object)]
public class SignalObject
{
}
[Fact]
@ -94,7 +97,7 @@ namespace Qml.Net.Tests.Qml
var signalObject = new SignalObject();
Mock.Setup(x => x.GetSignalObject()).Returns(signalObject);
Mock.Setup(x => x.SignalRaised).Returns(false);
RunQmlTest(
"test",
@"
@ -107,7 +110,7 @@ namespace Qml.Net.Tests.Qml
Mock.VerifySet(x => x.SignalRaised = true, Times.Once);
}
[Fact]
public void Can_raise_signal_from_qml_with_args()
{
@ -115,7 +118,7 @@ namespace Qml.Net.Tests.Qml
Mock.Setup(x => x.GetSignalObject()).Returns(signalObject);
Mock.Setup(x => x.SignalRaised).Returns(false);
Mock.Setup(x => x.MethodWithArgs("arg1", 3));
RunQmlTest(
"test",
@"
@ -130,14 +133,14 @@ namespace Qml.Net.Tests.Qml
Mock.VerifySet(x => x.SignalRaised = true, Times.Once);
Mock.Verify(x => x.MethodWithArgs("arg1", 3), Times.Once);
}
[Fact(Skip = "This was broken when issue #71 was resolved. If you need this, file an issue.")]
public void Can_raise_signal_from_qml_different_retrieval_of_net_instance()
{
var signalObject = new SignalObject();
Mock.Setup(x => x.GetSignalObject()).Returns(signalObject);
Mock.Setup(x => x.SignalRaised).Returns(false);
RunQmlTest(
"test",
@"
@ -162,7 +165,7 @@ namespace Qml.Net.Tests.Qml
signalObject.ActivateSignal("testSignal");
});
Mock.Setup(x => x.SignalRaised).Returns(false);
RunQmlTest(
"test",
@"
@ -175,12 +178,12 @@ namespace Qml.Net.Tests.Qml
Mock.VerifySet(x => x.SignalRaised = true, Times.Once);
}
[Fact]
public void Can_raise_changed_default_signal_from_net()
{
Mock.Setup(x => x.SignalRaised).Returns(false);
RunQmlTest(
"test",
@"
@ -192,12 +195,12 @@ namespace Qml.Net.Tests.Qml
Mock.VerifySet(x => x.SignalRaised = true, Times.Once);
}
[Fact]
public void Can_raise_changed_custom_signal_from_net()
{
Mock.Setup(x => x.SignalRaised).Returns(false);
RunQmlTest(
"test",
@"
@ -214,7 +217,7 @@ namespace Qml.Net.Tests.Qml
public void Can_not_raise_invalid_changed_signal_from_net()
{
Mock.Setup(x => x.SignalRaised).Returns(false);
RunQmlTest(
"test",
@"
@ -226,7 +229,7 @@ namespace Qml.Net.Tests.Qml
Mock.VerifySet(x => x.SignalRaised = true, Times.Never);
}
[Fact]
public void Can_raise_signal_from_net_with_args()
{
@ -238,7 +241,7 @@ namespace Qml.Net.Tests.Qml
});
Mock.Setup(x => x.SignalRaised).Returns(false);
Mock.Setup(x => x.MethodWithArgs("arg1", 3));
RunQmlTest(
"test",
@"
@ -253,27 +256,27 @@ namespace Qml.Net.Tests.Qml
Mock.VerifySet(x => x.SignalRaised = true, Times.Once);
Mock.Verify(x => x.MethodWithArgs("arg1", 3), Times.Once);
}
[Fact]
public void Can_attach_delegate_to_signal_when_object_not_in_qml()
{
var o = new SignalObject();
string message1 = null;
string message2 = null;
o.AttachToSignal("testSignalWithArgs1", new Action<string, int>((m, _) => { message1 = m; }));
o.AttachToSignal("testSignalWithArgs2", new Action<string,int>((m, _) => { message2 = m; }));
o.AttachToSignal("testSignalWithArgs2", new Action<string, int>((m, _) => { message2 = m; }));
o.ActivateSignal("testSignalWithArgs1", "message1", 3);
message1.Should().Be("message1");
message2.Should().BeNull();
message1 = null;
o.ActivateSignal("testSignalWithArgs2", "message2", 4);
message1.Should().BeNull();
message2.Should().Be("message2");
}
[Fact]
public void Can_raise_net_signal_from_qml_when_added_before_qml()
{
@ -281,7 +284,7 @@ namespace Qml.Net.Tests.Qml
string message = null;
o.AttachToSignal("testSignalWithArgs1", new Action<string, int>((m, _) => message = m));
Mock.Setup(x => x.GetSignalObject()).Returns(o);
RunQmlTest(
"test",
@"
@ -291,7 +294,7 @@ namespace Qml.Net.Tests.Qml
message.Should().Be("from qml");
}
[Fact]
public void Can_raise_net_signal_from_qml_when_added_after_qml()
{
@ -302,7 +305,7 @@ namespace Qml.Net.Tests.Qml
{
o.AttachToSignal("testSignalWithArgs1", new Action<string, int>((m, _) => message = m));
});
RunQmlTest(
"test",
@"
@ -327,7 +330,7 @@ namespace Qml.Net.Tests.Qml
{
paramResult = p;
}));
RunQmlTest(
"test",
@"
@ -335,7 +338,7 @@ namespace Qml.Net.Tests.Qml
var param = test.getTestObject()
instance.testSignalWithNetArg(param)
");
paramResult.Should().NotBeNull();
paramResult.SomeStringProperty.Should().NotBeNull(param.SomeStringProperty);
}
@ -358,14 +361,14 @@ namespace Qml.Net.Tests.Qml
{
paramResult = p;
}));
RunQmlTest(
"test",
@"
var instance = test.getSignalObject()
test.testMethod()
");
paramResult.Should().NotBeNull();
paramResult.SomeStringProperty.Should().NotBeNull(param.SomeStringProperty);
}

View file

@ -15,7 +15,8 @@ namespace Qml.Net.Tests.Qml
[Fact]
public void Can_register_singleton()
{
NetTestHelper.RunQml(qmlApplicationEngine,
NetTestHelper.RunQml(
qmlApplicationEngine,
@"
import QtQuick 2.0
import tests 1.0

View file

@ -12,7 +12,6 @@ namespace Qml.Net.Tests.Qml
public virtual void MethodParameter(string value)
{
}
public virtual string MethodReturn()

View file

@ -12,7 +12,6 @@ namespace Qml.Net.Tests.Qml
public virtual void MethodParameter(uint value)
{
}
public virtual uint MethodReturn()

View file

@ -10,16 +10,16 @@ namespace Qml.Net.Tests.Types
{
public class CallbacksTests : BaseTests
{
class TestObject
{
public void Method(TestObject o)
{
Object = o;
}
public TestObject Object { get; set; }
class TestObject
{
public void Method(TestObject o)
{
Object = o;
}
public TestObject Object { get; set; }
}
[Fact]
public void Can_call_is_type_valid()
{
@ -42,35 +42,35 @@ namespace Qml.Net.Tests.Types
// NetReference is still alive, so the weak reference must be alive as well.
GC.Collect(GC.MaxGeneration);
reference.IsAlive.Should().BeTrue();
instance.Dispose();
// NetReference has been destroyed, so the handle should have been released.
GC.Collect(GC.MaxGeneration);
reference.IsAlive.Should().BeFalse();
}
[Fact]
public void Can_instantiate_type()
{
var type = NetTypeManager.GetTypeInfo<TestObject>();
using(var instance = new NetReference(Interop.Callbacks.InstantiateType(type.Handle), false))
using (var instance = new NetReference(Interop.Callbacks.InstantiateType(type.Handle), false))
{
instance.Instance.Should().NotBeNull();
instance.Instance.Should().BeOfType<TestObject>();
}
}
[Fact]
public void Can_invoke_method()
{
var o = new TestObject();
var type = NetTypeManager.GetTypeInfo<TestObject>();
[Fact]
public void Can_invoke_method()
{
var o = new TestObject();
var type = NetTypeManager.GetTypeInfo<TestObject>();
type.EnsureLoaded();
var method = type.GetMethod(0);
var instance = NetReference.CreateForObject(o);
var method = type.GetMethod(0);
var instance = NetReference.CreateForObject(o);
// This will jump to native, to then call the .NET delegate (round trip).
// The purpose is to simulate Qml invoking a method, sending .NET instance back.
// We will inspect the returned instance that it got back to verify that it

View file

@ -8,9 +8,8 @@ namespace Qml.Net.Tests.Types
{
class TestObject
{
}
[Fact]
public void Can_create_net_instance()
{

View file

@ -12,12 +12,11 @@ namespace Qml.Net.Tests.Types
{
public void TestMethod()
{
}
public int TestProperty { get; set; }
}
[Fact]
public void Can_get_net_type()
{
@ -35,29 +34,28 @@ namespace Qml.Net.Tests.Types
{
public void TestMethod(int parameter1, TestType1 parameter2)
{
}
}
[Fact]
public void Can_get_method_parameters()
{
var typeInfo = NetTypeManager.GetTypeInfo<TestType2>();
typeInfo.EnsureLoaded();
typeInfo.MethodCount.Should().Be(1);
var method = typeInfo.GetMethod(0);
method.Should().NotBeNull();
method.ParameterCount.Should().Be(2);
var parameter1 = method.GetParameter(0);
parameter1.Should().NotBeNull();
parameter1.Name.Should().Be("parameter1");
var parameter1Type = parameter1.Type;
parameter1Type.Should().NotBeNull();
parameter1Type.ClassName.Should().Be("Int32");
var parameter2 = method.GetParameter(1);
parameter2.Should().NotBeNull();
parameter2.Name.Should().Be("parameter2");
@ -88,10 +86,9 @@ namespace Qml.Net.Tests.Types
{
public void TestMethod()
{
}
}
[Fact]
public void Can_get_method_without_return_type()
{
@ -105,7 +102,6 @@ namespace Qml.Net.Tests.Types
{
public void ThisIsMethodName()
{
}
}
@ -122,7 +118,7 @@ namespace Qml.Net.Tests.Types
{
public string Property { get; set; }
}
[Fact]
public void Can_get_property()
{
@ -142,9 +138,8 @@ namespace Qml.Net.Tests.Types
[Signal("testSignal", NetVariantType.DateTime, NetVariantType.Object)]
public class TestType7
{
}
[Fact]
public void Can_get_signal()
{
@ -164,7 +159,7 @@ namespace Qml.Net.Tests.Types
[NotifySignal("signalName")]
public string Property { get; set; }
}
[Fact]
public void Can_get_notifiy_signal_for_property()
{
@ -219,13 +214,12 @@ namespace Qml.Net.Tests.Types
{
return null;
}
public class InnerType
{
}
}
[Fact]
public void Can_lazy_load_types()
{
@ -246,12 +240,10 @@ namespace Qml.Net.Tests.Types
{
public void LocalMethod()
{
}
public static void StaticMethod()
{
}
}
@ -270,7 +262,7 @@ namespace Qml.Net.Tests.Types
{
public string[] Property { get; set; }
}
[Fact]
public void Can_detect_array_type()
{
@ -286,7 +278,7 @@ namespace Qml.Net.Tests.Types
public class TestType14
{
public List<int> Prop1 { get; set; }
public System.Collections.ArrayList Prop2 { get; set; }
}

View file

@ -40,12 +40,12 @@ namespace Qml.Net.Tests.Types
{
variant1.String = "test1";
variant2.String = "test2";
list.Add(variant1);
list.Add(variant2);
list.Count.Should().Be(2);
list.Remove(0);
list.Count.Should().Be(1);
@ -64,12 +64,12 @@ namespace Qml.Net.Tests.Types
{
variant1.String = "test1";
variant2.String = "test2";
list.Add(variant1);
list.Add(variant2);
list.Count.Should().Be(2);
list.Clear();
list.Count.Should().Be(0);

View file

@ -13,7 +13,7 @@ namespace Qml.Net
_handle = handle;
_ownesHandle = ownsHandle;
}
~BaseDisposable()
{
Dispose(false);
@ -27,21 +27,21 @@ namespace Qml.Net
{
throw new ObjectDisposedException($"Type {GetType().Name} is disposed.");
}
return _handle;
}
}
public void Dispose()
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
GC.SuppressFinalize(this);
}
protected void Dispose(bool disposing)
{
if (_disposed) return;
if (disposing)
{
DisposeManaged();
@ -59,7 +59,6 @@ namespace Qml.Net
protected virtual void DisposeManaged()
{
}
protected abstract void DisposeUnmanaged(IntPtr ptr);

View file

@ -10,7 +10,7 @@ namespace Qml.Net.Extensions
{
return null;
}
if (typeof(T) != typeof(int) && typeof(T) != typeof(string))
{
// Only enumerables of int and string are currently supported
@ -21,7 +21,7 @@ namespace Qml.Net.Extensions
try
{
var length = (int)value.GetProperty("length");
for (var i = 0; i < length; i++)
{
var item = value.GetItemAtIndex(i);

View file

@ -36,24 +36,24 @@ namespace Qml.Net
return ResolvePathResult.FromSuccess(library);
}
}
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
internal delegate IntPtr GetExportedSymbolDelegate([MarshalAs(UnmanagedType.LPStr)]string symbolName);
internal static GetExportedSymbolDelegate GetExportedSymbol;
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
private delegate int NativeRunCallbackDelegate(IntPtr app, IntPtr engine);
public delegate int NetRunCallbackDelegate();
public static int Run(string[] args, Func<string[], QGuiApplication, QQmlApplicationEngine, NetRunCallbackDelegate, int> action)
{
if (args.Length < 4)
{
throw new Exception("Args is invalid, must contain three entries which are pointers to native types.");
}
var appPtr = new IntPtr((long)ulong.Parse(args[0]));
var enginePtr = new IntPtr((long)ulong.Parse(args[1]));
var callbackPtr = new IntPtr((long)ulong.Parse(args[2]));

View file

@ -7,7 +7,7 @@ namespace Qml.Net
bool IsCallable { get; }
bool IsArray { get; }
object GetProperty(string propertyName);
object GetItemAtIndex(int arrayIndex);

View file

@ -1,7 +1,7 @@
using Qml.Net.Internal.Types;
using System;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using Qml.Net.Internal.Types;
namespace Qml.Net.Internal.Behaviors
{
@ -14,17 +14,18 @@ namespace Qml.Net.Internal.Behaviors
Name = name;
SignalName = signalName;
}
// ReSharper disable once MemberCanBePrivate.Local
// ReSharper disable once UnusedAutoPropertyAccessor.Local
public string Name { get; }
public string SignalName { get; }
}
private class MvvmTypeInfo
{
private readonly Dictionary<string, MvvmPropertyInfo> _propertyInfos = new Dictionary<string, MvvmPropertyInfo>();
// ReSharper disable once UnusedMember.Local
public Type Type { get; set; }
@ -40,7 +41,7 @@ namespace Qml.Net.Internal.Behaviors
}
private static readonly Dictionary<Type, MvvmTypeInfo> TypeInfos = new Dictionary<Type, MvvmTypeInfo>();
public bool IsApplicableFor(Type type)
{
return typeof(INotifyPropertyChanged).IsAssignableFrom(type);
@ -54,7 +55,7 @@ namespace Qml.Net.Internal.Behaviors
}
if (!(instance is INotifyPropertyChanged castedInstance))
{
//invalid type
// Invalid type.
return;
}
castedInstance.PropertyChanged += PropertyChangedHandler;
@ -68,7 +69,7 @@ namespace Qml.Net.Internal.Behaviors
}
if (!(instance is INotifyPropertyChanged castedInstance))
{
//invalid type
// Invalid type.
return;
}
@ -81,7 +82,8 @@ namespace Qml.Net.Internal.Behaviors
{
return;
}
//fire signal according to the property that got changed
// Fire signal according to the property that got changed.
var type = sender.GetType();
if (TypeInfos.TryGetValue(type, out var typeInfo))
{
@ -118,30 +120,32 @@ namespace Qml.Net.Internal.Behaviors
var property = netTypeInfo.GetProperty(i);
if (property.NotifySignal != null)
{
//in this case some other behavior or the user has already set up a notify signal for this property
//we don't want to destroy that
// In this case some other behavior or the user has already set up a notify signal for this property.
// We don't want to destroy that.
mvvmTypeInfo.AddPropertyInfo(property.Name, property.NotifySignal.Name);
continue;
}
var signalName = CalculateSignalNameFromPropertyName(property.Name);
mvvmTypeInfo.AddPropertyInfo(property.Name, signalName);
//check if this signal already has been registered
for(var signalIndex = 0; signalIndex < netTypeInfo.SignalCount; signalIndex++)
// Check if this signal already has been registered.
for (var signalIndex = 0; signalIndex < netTypeInfo.SignalCount; signalIndex++)
{
var signal = netTypeInfo.GetSignal(signalIndex);
if(string.Equals(signalName, signal.Name))
if (string.Equals(signalName, signal.Name))
{
existingSignalIndex = signalIndex;
break;
}
}
if(existingSignalIndex.HasValue)
if (existingSignalIndex.HasValue)
{
//signal for this property is already existent but not registered (we check that above)
// Signal for this property is already existent but not registered (we check that above).
property.NotifySignal = netTypeInfo.GetSignal(existingSignalIndex.Value);
continue;
}
//create a new signal and link it to the property
// Create a new signal and link it to the property.
var notifySignalInfo = new NetSignalInfo(netTypeInfo, signalName);
netTypeInfo.AddSignal(notifySignalInfo);
property.NotifySignal = notifySignalInfo;

View file

@ -1,6 +1,4 @@
using Qml.Net.Internal.Qml;
using Qml.Net.Internal.Types;
using System;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
@ -8,6 +6,8 @@ using System.Reflection;
using System.Runtime.InteropServices;
using System.Threading.Tasks;
using Microsoft.CSharp.RuntimeBinder;
using Qml.Net.Internal.Qml;
using Qml.Net.Internal.Types;
namespace Qml.Net.Internal
{
@ -24,11 +24,15 @@ namespace Qml.Net.Internal
using (var type = new NetTypeInfo(t))
{
var typeInfo = Type.GetType(type.FullTypeName);
if (typeInfo == null) throw new InvalidOperationException();
if (typeInfo == null)
{
throw new InvalidOperationException();
}
type.ClassName = typeInfo.Name;
type.PrefVariantType = GetPrefVariantType(typeInfo);
// All the methods/properties/signals are later populated when needed.
}
}
@ -42,10 +46,13 @@ namespace Qml.Net.Internal
{
throw new InvalidOperationException($"Invalid type {type.FullTypeName}");
}
// Don't grab properties and methods for system-level types.
if (Helpers.IsPrimitive(typeInfo)) return;
// Don't grab properties and methods for system-level types.
if (Helpers.IsPrimitive(typeInfo))
{
return;
}
if (typeInfo.IsArray)
{
type.IsArray = true;
@ -58,13 +65,13 @@ namespace Qml.Net.Internal
}
else if (typeInfo.IsGenericType)
{
if(typeof(IList<>).IsAssignableFrom(typeInfo.GetGenericTypeDefinition()))
if (typeof(IList<>).IsAssignableFrom(typeInfo.GetGenericTypeDefinition()))
{
type.IsList = true;
}
}
}
foreach (var methodInfo in typeInfo.GetMethods(BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static))
{
if (methodInfo.IsGenericMethod) continue; // No generics supported.
@ -89,7 +96,7 @@ namespace Qml.Net.Internal
}
var signals = new Dictionary<string, NetSignalInfo>();
foreach (var signalAttribute in typeInfo.GetCustomAttributes().OfType<SignalAttribute>())
{
if (string.IsNullOrEmpty(signalAttribute.Name))
@ -101,7 +108,7 @@ namespace Qml.Net.Internal
{
throw new InvalidOperationException($"Signal {signalAttribute.Name} for {typeInfo.Name} must begin with a lower case letter.");
}
var signal = new NetSignalInfo(type, signalAttribute.Name);
foreach (var parameter in signalAttribute.Parameters)
{
@ -110,7 +117,7 @@ namespace Qml.Net.Internal
type.AddSignal(signal);
signals.Add(signal.Name, signal);
}
foreach (var propertyInfo in typeInfo.GetProperties(BindingFlags.Public | BindingFlags.Instance))
{
if (Helpers.IsPrimitive(propertyInfo.DeclaringType)) continue;
@ -125,10 +132,11 @@ namespace Qml.Net.Internal
name = $"{propertyInfo.Name}Changed";
name = char.ToLower(name[0]) + name.Substring(1);
}
if (signals.ContainsKey(name))
{
notifySignal = signals[name];
// Make sure the signal we are referencing has no parameters.
if (notifySignal.ParameterCount != 0)
{
@ -142,12 +150,12 @@ namespace Qml.Net.Internal
{
throw new InvalidOperationException($"Signal {name} for {typeInfo.Name} must begin with a lower case letter.");
}
notifySignal = new NetSignalInfo(type, name);
type.AddSignal(notifySignal);
}
}
using (var property = new NetPropertyInfo(
type,
propertyInfo.Name,
@ -166,7 +174,7 @@ namespace Qml.Net.Internal
InteropBehaviors.OnNetTypeInfoCreated(type, typeInfo);
}
}
public void ReleaseNetReference(UInt64 objectId)
{
NetReference.OnRelease(objectId);
@ -174,7 +182,7 @@ namespace Qml.Net.Internal
public void ReleaseNetDelegateGCHandle(IntPtr handle)
{
NetDelegate.ReleaseGCHandle(((GCHandle)handle));
NetDelegate.ReleaseGCHandle((GCHandle)handle);
}
public IntPtr InstantiateType(IntPtr type)
@ -183,9 +191,9 @@ namespace Qml.Net.Internal
{
var typeName = Utilities.ContainerToString(Interop.NetTypeInfo.GetFullTypeName(type));
var typeInfo = Type.GetType(typeName);
if(typeInfo == null) throw new InvalidOperationException($"Invalid type {typeName}");
if (typeInfo == null) throw new InvalidOperationException($"Invalid type {typeName}");
var netReference = NetReference.CreateForObject(TypeCreator.Create(typeInfo));
// When .NET collects this NetReference, we don't want it to delete this
// handle. Ownership has been passed to the caller.
return Interop.NetReference.Clone(netReference.Handle);
@ -198,24 +206,23 @@ namespace Qml.Net.Internal
public void ReadProperty(IntPtr p, IntPtr t, IntPtr ip, IntPtr r)
{
using(var property = new NetPropertyInfo(p))
using(var target = new NetReference(t))
using(var indexParameter = ip != IntPtr.Zero ? new NetVariant(ip) : null)
using(var result = new NetVariant(r))
using (var property = new NetPropertyInfo(p))
using (var target = new NetReference(t))
using (var indexParameter = ip != IntPtr.Zero ? new NetVariant(ip) : null)
using (var result = new NetVariant(r))
{
var o = target.Instance;
var propertInfo = o.GetType()
.GetProperty(property.Name, BindingFlags.Instance | BindingFlags.Public);
if(propertInfo == null)
if (propertInfo == null)
throw new InvalidOperationException($"Invalid property {property.Name}");
if (indexParameter != null)
{
object indexParameterValue = null;
Helpers.Unpackvalue(ref indexParameterValue, indexParameter);
Helpers.PackValue(propertInfo.GetValue(o, new[]{indexParameterValue}), result);
Helpers.PackValue(propertInfo.GetValue(o, new[] { indexParameterValue }), result);
}
else
{
@ -246,7 +253,7 @@ namespace Qml.Net.Internal
{
object indexParameterValue = null;
Helpers.Unpackvalue(ref indexParameterValue, indexParameter);
propertInfo.SetValue(o, newValue, new[]{indexParameterValue});
propertInfo.SetValue(o, newValue, new[] { indexParameterValue });
}
else
{
@ -263,7 +270,7 @@ namespace Qml.Net.Internal
using (var result = r != IntPtr.Zero ? new NetVariant(r) : null)
{
var instance = target.Instance;
List<object> methodParameters = null;
if (parameters.Count > 0)
@ -292,11 +299,12 @@ namespace Qml.Net.Internal
else if (methods.Count > 1)
{
// This is an overload.
// TODO: Make this more performant. https://github.com/pauldotknopf/Qml.Net/issues/39
// Get all the parameters for the method we are invoking.
var parameterTypes = method.GetAllParameters().Select(x => x.Type.FullTypeName).ToList();
// And find a good method to invoke.
foreach (var potentialMethod in methods)
{
@ -330,7 +338,7 @@ namespace Qml.Net.Internal
}
var returnObject = methodInfo.Invoke(instance, methodParameters?.ToArray());
if (result == null)
{
// this method doesn't have return type
@ -384,8 +392,8 @@ namespace Qml.Net.Internal
public async Task AwaitTask(IntPtr t, IntPtr sc, IntPtr fc)
{
using (var target = new NetReference(t))
using(var successCallback = new NetJsValue(sc))
using(var failureCallback = fc != IntPtr.Zero ? new NetJsValue(fc) : null)
using (var successCallback = new NetJsValue(sc))
using (var failureCallback = fc != IntPtr.Zero ? new NetJsValue(fc) : null)
{
var taskObject = target.Instance;
if (taskObject is Task task)
@ -447,7 +455,7 @@ namespace Qml.Net.Internal
}
}
}
private NetVariantType GetPrefVariantType(Type typeInfo)
{
if (typeInfo == typeof(bool))
@ -478,7 +486,7 @@ namespace Qml.Net.Internal
return GetPrefVariantType(typeInfo.GetGenericArguments()[0]);
// ReSharper restore TailRecursiveCall
}
return NetVariantType.Object;
}
}

View file

@ -12,23 +12,25 @@ namespace Qml.Net.Internal
{
return false;
}
if (type.Namespace == "System")
{
if (type.Name == "Exception")
{
return false;
}
if (type.Name == "Array")
{
return false;
}
return true;
}
return false;
}
public static void PackValue(object source, NetVariant destination)
{
if (source == null)
@ -40,26 +42,26 @@ namespace Qml.Net.Internal
var type = source.GetType();
if (type == typeof(bool))
destination.Bool = (bool)source;
else if(type == typeof(char))
else if (type == typeof(char))
destination.Char = (char)source;
else if(type == typeof(float))
else if (type == typeof(float))
destination.Float = (float)source;
else if(type == typeof(double))
else if (type == typeof(double))
destination.Double = (double)source;
else if (type == typeof(int))
destination.Int = (int)source;
else if(type == typeof(uint))
else if (type == typeof(uint))
destination.UInt = (uint)source;
else if (type == typeof(long))
destination.Long = (long)source;
else if(type == typeof(ulong))
else if (type == typeof(ulong))
destination.ULong = (ulong)source;
else if (type == typeof(string))
destination.String = (string)source;
else if (type == typeof(DateTimeOffset))
destination.DateTime = ((DateTimeOffset) source).DateTime;
destination.DateTime = ((DateTimeOffset)source).DateTime;
else if (typeof(INetJsValue).IsAssignableFrom(type))
destination.JsValue = ((NetJsValue.NetJsValueDynamic) source).JsValue;
destination.JsValue = ((NetJsValue.NetJsValueDynamic)source).JsValue;
else
{
destination.Instance = NetReference.CreateForObject(source);
@ -67,7 +69,7 @@ namespace Qml.Net.Internal
}
}
public static void Unpackvalue(ref object destination, NetVariant source)
public static void Unpackvalue(ref object destination, NetVariant source)
{
switch (source.VariantType)
{

View file

@ -1,7 +1,5 @@
using Qml.Net.Internal.Types;
using System;
using System.Collections.Generic;
using System.Text;
using System;
using Qml.Net.Internal.Types;
namespace Qml.Net.Internal
{

View file

@ -13,7 +13,7 @@ namespace Qml.Net.Internal
internal static class Interop
{
static readonly CallbacksImpl DefaultCallbacks = new CallbacksImpl(new DefaultCallbacks());
static Interop()
{
string pluginsDirectory = null;
@ -22,7 +22,7 @@ namespace Qml.Net.Internal
IPathResolver pathResolver = null;
IPlatformLoader loader = null;
if (Host.GetExportedSymbol != null)
{
// We are loading exported functions from the currently running executable.
@ -69,7 +69,7 @@ namespace Qml.Net.Internal
}
}
}
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
if (!string.IsNullOrEmpty(libDirectory) && Directory.Exists(libDirectory))
@ -78,7 +78,8 @@ namespace Qml.Net.Internal
// the folder to the path. The reason is because QML plugins aren't
// in the same directory and have trouble finding dependencies
// that are within our lib folder.
Environment.SetEnvironmentVariable("PATH",
Environment.SetEnvironmentVariable(
"PATH",
Environment.GetEnvironmentVariable("PATH") + $";{libDirectory}");
}
}
@ -112,11 +113,11 @@ namespace Qml.Net.Internal
Utilities = LoadInteropType<UtilitiesInterop>(library, loader);
QtWebEngine = LoadInteropType<QtWebEngineInterop>(library, loader);
if(!string.IsNullOrEmpty(pluginsDirectory))
if (!string.IsNullOrEmpty(pluginsDirectory))
{
Qt.PutEnv("QT_PLUGIN_PATH", pluginsDirectory);
}
if(!string.IsNullOrEmpty(qmlDirectory))
if (!string.IsNullOrEmpty(qmlDirectory))
{
Qt.PutEnv("QML2_IMPORT_PATH", qmlDirectory);
}
@ -128,48 +129,49 @@ namespace Qml.Net.Internal
public static CallbacksInterop Callbacks { get; }
public static NetTypeInfoInterop NetTypeInfo { get; }
public static NetMethodInfoInterop NetMethodInfo { get; }
public static NetPropertyInfoInterop NetPropertyInfo { get; }
public static NetTypeManagerInterop NetTypeManager { get; }
public static QGuiApplicationInterop QGuiApplication { get; }
public static QQmlApplicationEngineInterop QQmlApplicationEngine { get; }
public static NetVariantInterop NetVariant { get; }
public static NetReferenceInterop NetReference { get; }
public static NetVariantListInterop NetVariantList { get; }
public static NetTestHelperInterop NetTestHelper { get; }
public static NetSignalInfoInterop NetSignalInfo { get; }
public static QResourceInterop QResource { get; }
public static NetDelegateInterop NetDelegate { get; }
public static NetJsValueInterop NetJsValue { get; }
public static QQuickStyleInterop QQuickStyle { get; }
public static QtInterop QtInterop { get; }
public static UtilitiesInterop Utilities { get; }
public static QtWebEngineInterop QtWebEngine { get; }
private static T LoadInteropType<T>(IntPtr library, NetNativeLibLoader.Loader.IPlatformLoader loader) where T:new()
private static T LoadInteropType<T>(IntPtr library, NetNativeLibLoader.Loader.IPlatformLoader loader)
where T : new()
{
var result = new T();
LoadDelegates(result, library, loader);
return result;
}
private static void LoadDelegates(object o, IntPtr library, NetNativeLibLoader.Loader.IPlatformLoader loader)
{
foreach (var property in o.GetType().GetProperties())

View file

@ -8,6 +8,7 @@ namespace Qml.Net.Internal
internal static class InteropBehaviors
{
private static List<IQmlInteropBehavior> _QmlInteropBehaviors = new List<IQmlInteropBehavior>();
public static IEnumerable<IQmlInteropBehavior> QmlInteropBehaviors => _QmlInteropBehaviors;
private static IEnumerable<IQmlInteropBehavior> GetApplicableInteropBehaviors(Type forType)
@ -16,13 +17,13 @@ namespace Qml.Net.Internal
.Where(b => b.IsApplicableFor(forType));
}
/// <summary>
/// Registers an additional Qml Interop behavior. This behavior only gets applied to types and instances created or registered after this behavior registration
/// </summary>
/// <param name="behavior"></param>
/// <summary>
/// Registers an additional Qml Interop behavior. This behavior only gets applied to types and instances created or registered after this behavior registration
/// </summary>
/// <param name="behavior">IQmlInteropBehavior</param>
public static void RegisterQmlInteropBehavior(IQmlInteropBehavior behavior, bool addIfTypeAlreadyExists = false)
{
if(!addIfTypeAlreadyExists && _QmlInteropBehaviors.Any(ib => ib.GetType() == behavior.GetType()))
if (!addIfTypeAlreadyExists && _QmlInteropBehaviors.Any(ib => ib.GetType() == behavior.GetType()))
{
return;
}

View file

@ -19,7 +19,7 @@ namespace Qml.Net.Internal
{
var result = _original.Resolve(library);
if(!result.IsSuccess && library == "QmlNet")
if (!result.IsSuccess && library == "QmlNet")
{
// Try to let .NET load the library.
try
@ -39,7 +39,7 @@ namespace Qml.Net.Internal
}
// ReSharper disable EmptyGeneralCatchClause
catch (Exception)
// ReSharper restore EmptyGeneralCatchClause
// ReSharper restore EmptyGeneralCatchClause
{
}
}

View file

@ -18,7 +18,7 @@ namespace Qml.Net.Internal
{
var result = _original.Resolve(library);
if(!result.IsSuccess && library == "QmlNet")
if (!result.IsSuccess && library == "QmlNet")
{
// Try to let .NET load the library.
try
@ -32,14 +32,13 @@ namespace Qml.Net.Internal
{
return result;
}
var sym = dlsym(dll, "qml_net_getVersion");
if (sym == IntPtr.Zero)
{
return result;
}
var info = new DlInfo();
if (dladdr(sym, ref info) != 1)
{
@ -48,11 +47,12 @@ namespace Qml.Net.Internal
var location = Marshal.PtrToStringAnsi(info.fname);
if(File.Exists(location))
if (File.Exists(location))
{
return ResolvePathResult.FromSuccess(location);
}
}
// ReSharper disable EmptyGeneralCatchClause
catch (Exception)
// ReSharper restore EmptyGeneralCatchClause
@ -65,13 +65,13 @@ namespace Qml.Net.Internal
[DllImport("libQmlNet.dylib")]
static extern long qml_net_getVersion();
[DllImport("dl")]
static extern IntPtr dlopen(string fileName, SymbolFlag flags);
[DllImport("dl")]
static extern IntPtr dlsym(IntPtr handle, string name);
[DllImport("dl")]
static extern int dladdr(IntPtr handle, ref DlInfo info);
@ -82,7 +82,7 @@ namespace Qml.Net.Internal
private IntPtr notUsed2;
private IntPtr notUsed3;
}
[Flags]
private enum SymbolFlag
{

View file

@ -4,6 +4,6 @@ namespace Qml.Net.Internal
{
public class NativeSymbolAttribute : Attribute
{
public string Entrypoint { get; set; }
public string Entrypoint { get; set; }
}
}

View file

@ -13,15 +13,14 @@ namespace Qml.Net.Internal
public void Dispose()
{
}
public Dictionary<string, List<Delegate>> Delegates { get; }
}
internal static class ObjectSignals
{
private static readonly ConditionalWeakTable<object, ObjectSignalCollection> Signals
private static readonly ConditionalWeakTable<object, ObjectSignalCollection> Signals
= new ConditionalWeakTable<object, ObjectSignalCollection>();
public static void AttachDelegateToSignal(this object obj, string signal, Delegate del)
@ -31,9 +30,9 @@ namespace Qml.Net.Internal
{
signals.Delegates[signal].Add(del);
}
signals.Delegates.Add(signal, new List<Delegate>{del});
signals.Delegates.Add(signal, new List<Delegate> { del });
}
public static List<Delegate> GetAttachedDelegates(this object obj, string signal)
{
if (Signals.TryGetValue(obj, out var signalCollection))

View file

@ -38,7 +38,7 @@ namespace Qml.Net.Internal
~ObjectId()
{
if(_Tagger != null)
if (_Tagger != null)
{
_Tagger.FreeId(Id);
}

View file

@ -9,7 +9,6 @@ namespace Qml.Net.Internal.Qml
public NetJsValue(IntPtr handle, bool ownsHandle = true)
: base(handle, ownsHandle)
{
}
public bool IsCallable => Interop.NetJsValue.IsCallable(Handle);
@ -21,11 +20,11 @@ namespace Qml.Net.Internal.Qml
var result = Interop.NetJsValue.Call(Handle, parameters?.Handle ?? IntPtr.Zero);
return result != IntPtr.Zero ? new NetVariant(result) : null;
}
public object Call(params object[] parameters)
{
NetVariantList variants = null;
if (parameters != null && parameters.Length > 0)
{
variants = new NetVariantList();
@ -38,20 +37,20 @@ namespace Qml.Net.Internal.Qml
}
}
}
var result = Call(variants);
variants?.Dispose();
if (result == null)
{
return null;
}
object returnValue = null;
Helpers.Unpackvalue(ref returnValue, result);
result.Dispose();
return returnValue;
}
@ -105,7 +104,7 @@ namespace Qml.Net.Internal.Qml
}
public NetJsValue JsValue => _jsValue;
public bool IsCallable => _jsValue.IsCallable;
public bool IsArray => _jsValue.IsArray;
@ -142,14 +141,14 @@ namespace Qml.Net.Internal.Qml
public override bool TryInvoke(InvokeBinder binder, object[] args, out object result)
{
result = null;
if (!IsCallable)
{
return false;
}
result = Call(args);
return true;
}
@ -193,30 +192,37 @@ namespace Qml.Net.Internal.Qml
{
[NativeSymbol(Entrypoint = "net_js_value_destroy")]
public DestroyDel Destroy { get; set; }
public delegate void DestroyDel(IntPtr jsValue);
[NativeSymbol(Entrypoint = "net_js_value_isCallable")]
public IsCallableDel IsCallable { get; set; }
public delegate bool IsCallableDel(IntPtr jsValue);
[NativeSymbol(Entrypoint = "net_js_value_isArray")]
public IsArrayDel IsArray { get; set; }
public delegate bool IsArrayDel(IntPtr jsValue);
[NativeSymbol(Entrypoint = "net_js_value_call")]
public CallDel Call { get; set; }
public delegate IntPtr CallDel(IntPtr jsValue, IntPtr parameters);
[NativeSymbol(Entrypoint = "net_js_value_getProperty")]
public GetPropertyDel GetProperty { get; set; }
public delegate IntPtr GetPropertyDel(IntPtr jsValue, [MarshalAs(UnmanagedType.LPWStr)] string propertyName);
[NativeSymbol(Entrypoint = "net_js_value_getItemAtIndex")]
public GetItemAtIndexDel GetItemAtIndex { get; set; }
public delegate IntPtr GetItemAtIndexDel(IntPtr jsValue, int arrayIndex);
[NativeSymbol(Entrypoint = "net_js_value_setProperty")]
public SetPropertyDel SetProperty { get; set; }
public delegate void SetPropertyDel(IntPtr jsValue, [MarshalAs(UnmanagedType.LPWStr)] string propertyName, IntPtr value);
}
}

View file

@ -10,11 +10,12 @@ namespace Qml.Net.Internal.Qml
Interop.NetTestHelper.RunQml(qmlEngine.Handle, qml);
}
}
internal class NetTestHelperInterop
{
[NativeSymbol(Entrypoint = "net_test_helper_runQml")]
public RunQmlDel RunQml { get; set; }
public delegate void RunQmlDel(IntPtr qmlEngine, [MarshalAs(UnmanagedType.LPWStr)]string qml);
}
}

View file

@ -9,13 +9,11 @@ namespace Qml.Net.Internal.Qml
public NetVariant()
: this(Interop.NetVariant.Create())
{
}
public NetVariant(IntPtr handle, bool ownsHandle = true)
: base(handle, ownsHandle)
{
}
public NetVariantType VariantType => Interop.NetVariant.GetVariantType(Handle);
@ -35,19 +33,19 @@ namespace Qml.Net.Internal.Qml
get => Interop.NetVariant.GetBool(Handle);
set => Interop.NetVariant.SetBool(Handle, value);
}
public char Char
{
get => (char)Interop.NetVariant.GetChar(Handle);
set => Interop.NetVariant.SetChar(Handle, value);
}
public int Int
{
get => Interop.NetVariant.GetInt(Handle);
set => Interop.NetVariant.SetInt(Handle, value);
}
public uint UInt
{
get => Interop.NetVariant.GetUInt(Handle);
@ -71,28 +69,29 @@ namespace Qml.Net.Internal.Qml
get => Interop.NetVariant.GetFloat(Handle);
set => Interop.NetVariant.SetFloat(Handle, value);
}
public double Double
{
get => Interop.NetVariant.GetDouble(Handle);
set => Interop.NetVariant.SetDouble(Handle, value);
}
public string String
{
get => Utilities.ContainerToString(Interop.NetVariant.GetString(Handle));
set => Interop.NetVariant.SetString(Handle, value);
}
public DateTimeOffset? DateTime
{
get
{
var dateTime = new DateTimeContainer();
var dateTime = new DateTimeContainer();
Interop.NetVariant.GetDateTime(Handle, ref dateTime);
if (dateTime.IsNull)
return null;
return new DateTimeOffset(dateTime.Year,
return new DateTimeOffset(
dateTime.Year,
dateTime.Month,
dateTime.Day,
dateTime.Hour,
@ -101,6 +100,7 @@ namespace Qml.Net.Internal.Qml
dateTime.Msec,
TimeSpan.FromSeconds(dateTime.OffsetSeconds));
}
set
{
var dateTime = new DateTimeContainer();
@ -134,122 +134,161 @@ namespace Qml.Net.Internal.Qml
}
set => Interop.NetVariant.SetJsValue(Handle, value?.Handle ?? IntPtr.Zero);
}
public void Clear()
{
Interop.NetVariant.Clear(Handle);
}
protected override void DisposeUnmanaged(IntPtr ptr)
{
Interop.NetVariant.Destroy(ptr);
}
}
internal class NetVariantInterop
{
[NativeSymbol(Entrypoint = "net_variant_create")]
public CreateDel Create { get; set; }
public delegate IntPtr CreateDel();
[NativeSymbol(Entrypoint = "net_variant_destroy")]
public DestroyDel Destroy { get; set; }
public delegate void DestroyDel(IntPtr variant);
[NativeSymbol(Entrypoint = "net_variant_getVariantType")]
public GetVariantTypeDel GetVariantType { get; set; }
public delegate NetVariantType GetVariantTypeDel(IntPtr variant);
[NativeSymbol(Entrypoint = "net_variant_setNetReference")]
public SetNetReferenceDel SetNetReference { get; set; }
public delegate void SetNetReferenceDel(IntPtr variant, IntPtr instance);
[NativeSymbol(Entrypoint = "net_variant_getNetReference")]
public GetNetReferenceDel GetNetReference { get; set; }
public delegate IntPtr GetNetReferenceDel(IntPtr variant);
[NativeSymbol(Entrypoint = "net_variant_setBool")]
public SetBoolDel SetBool { get; set; }
public delegate void SetBoolDel(IntPtr variant, bool value);
[NativeSymbol(Entrypoint = "net_variant_getBool")]
public GetBoolDel GetBool { get; set; }
public delegate bool GetBoolDel(IntPtr variant);
[NativeSymbol(Entrypoint = "net_variant_setChar")]
public SetCharDel SetChar { get; set; }
public delegate void SetCharDel(IntPtr variant, ushort value);
[NativeSymbol(Entrypoint = "net_variant_getChar")]
public GetCharDel GetChar { get; set; }
public delegate ushort GetCharDel(IntPtr variant);
[NativeSymbol(Entrypoint = "net_variant_setInt")]
public SetIntDel SetInt { get; set; }
public delegate void SetIntDel(IntPtr variant, int value);
[NativeSymbol(Entrypoint = "net_variant_getInt")]
public GetIntDel GetInt { get; set; }
public delegate int GetIntDel(IntPtr variant);
[NativeSymbol(Entrypoint = "net_variant_setUInt")]
public SetUIntDel SetUInt { get; set; }
public delegate void SetUIntDel(IntPtr variant, uint value);
[NativeSymbol(Entrypoint = "net_variant_getUInt")]
public GetUIntDel GetUInt { get; set; }
public delegate uint GetUIntDel(IntPtr variant);
[NativeSymbol(Entrypoint = "net_variant_setLong")]
public SetLongDel SetLong { get; set; }
public delegate void SetLongDel(IntPtr variant, long value);
[NativeSymbol(Entrypoint = "net_variant_getLong")]
public GetLongDel GetLong { get; set; }
public delegate long GetLongDel(IntPtr variant);
[NativeSymbol(Entrypoint = "net_variant_setULong")]
public SetULongDel SetULong { get; set; }
public delegate void SetULongDel(IntPtr variant, ulong value);
[NativeSymbol(Entrypoint = "net_variant_getULong")]
public GetULongDel GetULong { get; set; }
public delegate ulong GetULongDel(IntPtr variant);
[NativeSymbol(Entrypoint = "net_variant_setFloat")]
public SetFloatDel SetFloat { get; set; }
public delegate void SetFloatDel(IntPtr variant, float value);
[NativeSymbol(Entrypoint = "net_variant_getFloat")]
public GetFloatDel GetFloat { get; set; }
public delegate float GetFloatDel(IntPtr variant);
[NativeSymbol(Entrypoint = "net_variant_setDouble")]
public SetDoubleDel SetDouble { get; set; }
public delegate void SetDoubleDel(IntPtr variant, double value);
[NativeSymbol(Entrypoint = "net_variant_getDouble")]
public GetDoubleDel GetDouble { get; set; }
public delegate double GetDoubleDel(IntPtr variant);
[NativeSymbol(Entrypoint = "net_variant_setString")]
public SetStringDel SetString { get; set; }
public delegate void SetStringDel(IntPtr variant, [MarshalAs(UnmanagedType.LPWStr)]string value);
[NativeSymbol(Entrypoint = "net_variant_getString")]
public GetStringDel GetString { get; set; }
public delegate IntPtr GetStringDel(IntPtr variant);
[NativeSymbol(Entrypoint = "net_variant_setDateTime")]
public SetDateTimeDel SetDateTime { get; set; }
public delegate void SetDateTimeDel(IntPtr variant, ref DateTimeContainer dateTime);
[NativeSymbol(Entrypoint = "net_variant_getDateTime")]
public GetDateTimeDel GetDateTime { get; set; }
public delegate void GetDateTimeDel(IntPtr variant, ref DateTimeContainer dateTime);
[NativeSymbol(Entrypoint = "net_variant_setJsValue")]
public SetJsValueDel SetJsValue { get; set; }
public delegate void SetJsValueDel(IntPtr variant, IntPtr jsValue);
[NativeSymbol(Entrypoint = "net_variant_getJsValue")]
public GetJsValueDel GetJsValue { get; set; }
public delegate IntPtr GetJsValueDel(IntPtr variant);
[NativeSymbol(Entrypoint = "net_variant_clear")]
public ClearDel Clear { get; set; }
public delegate void ClearDel(IntPtr variant);
}
[StructLayout(LayoutKind.Sequential)]
internal struct DateTimeContainer
{

View file

@ -7,13 +7,11 @@ namespace Qml.Net.Internal.Qml
public NetVariantList()
: this(Interop.NetVariantList.Create())
{
}
public NetVariantList(IntPtr handle, bool ownsHandle = true)
: base(handle, ownsHandle)
{
}
public int Count => Interop.NetVariantList.Count(Handle);
@ -39,37 +37,48 @@ namespace Qml.Net.Internal.Qml
{
Interop.NetVariantList.Clear(Handle);
}
protected override void DisposeUnmanaged(IntPtr ptr)
{
Interop.NetVariantList.Destroy(ptr);
}
}
internal class NetVariantListInterop
{
{
[NativeSymbol(Entrypoint = "net_variant_list_create")]
public CreateDel Create { get; set; }
public delegate IntPtr CreateDel();
[NativeSymbol(Entrypoint = "net_variant_list_destroy")]
public DestroyDel Destroy { get; set; }
public delegate void DestroyDel(IntPtr list);
[NativeSymbol(Entrypoint = "net_variant_list_count")]
public CountDel Count { get; set; }
public delegate int CountDel(IntPtr list);
[NativeSymbol(Entrypoint = "net_variant_list_add")]
public AddDel Add { get; set; }
public delegate void AddDel(IntPtr list, IntPtr variant);
[NativeSymbol(Entrypoint = "net_variant_list_get")]
public GetDel Get { get; set; }
public delegate IntPtr GetDel(IntPtr list, int index);
[NativeSymbol(Entrypoint = "net_variant_list_remove")]
public RemoveDel Remove { get; set; }
public delegate void RemoveDel(IntPtr list, int index);
[NativeSymbol(Entrypoint = "net_variant_list_clear")]
public ClearDel Clear { get; set; }
public delegate void ClearDel(IntPtr list);
}
}

View file

@ -26,26 +26,32 @@ namespace Qml.Net.Internal.Types
{
[NativeSymbol(Entrypoint = "type_info_callbacks_registerCallbacks")]
public RegisterCallbacksDel RegisterCallbacks { get; set; }
public delegate void RegisterCallbacksDel(ref Callbacks callbacks);
[NativeSymbol(Entrypoint = "type_info_callbacks_isTypeValid")]
public IsTypeValidDel IsTypeValid { get; set; }
public delegate bool IsTypeValidDel([MarshalAs(UnmanagedType.LPWStr)]string typeName);
[NativeSymbol(Entrypoint = "type_info_callbacks_releaseNetReferenceGCHandle")]
public ReleaseNetReferenceDel ReleaseNetReference { get; set; }
public delegate void ReleaseNetReferenceDel(UInt64 objectId);
[NativeSymbol(Entrypoint = "type_info_callbacks_releaseNetDelegateGCHandle")]
public ReleaseNetDelegateGCHandleDel ReleaseNetDelegateGCHandle { get; set; }
public delegate void ReleaseNetDelegateGCHandleDel(IntPtr handle);
[NativeSymbol(Entrypoint = "type_info_callbacks_instantiateType")]
public InstantiateTypeDel InstantiateType { get; set; }
public delegate IntPtr InstantiateTypeDel(IntPtr type);
[NativeSymbol(Entrypoint = "type_info_callbacks_invokeMethod")]
public InvokeMethodDel InvokeMethod { get; set; }
public delegate void InvokeMethodDel(IntPtr method, IntPtr target, IntPtr variants, IntPtr result);
}
@ -60,7 +66,7 @@ namespace Qml.Net.Internal.Types
void CreateLazyTypeInfo(IntPtr typeInfo);
void LoadTypeInfo(IntPtr typeInfo);
IntPtr InstantiateType(IntPtr type);
void ReadProperty(IntPtr property, IntPtr target, IntPtr indexProperty, IntPtr result);
@ -74,10 +80,10 @@ namespace Qml.Net.Internal.Types
bool RaiseNetSignals(IntPtr target, string signalName, IntPtr parameters);
Task AwaitTask(IntPtr target, IntPtr succesCallback, IntPtr failureCallback);
bool Serialize(IntPtr instance, IntPtr result);
}
internal class CallbacksImpl
{
readonly ICallbacks _callbacks;
@ -94,28 +100,28 @@ namespace Qml.Net.Internal.Types
RaiseNetSignalsDelegate _raiseNetSignalsDelegate;
AwaitTaskDelegate _awaitTaskDelegate;
SerializeDelegate _serializeDelegate;
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
delegate bool IsTypeValidDelegate([MarshalAs(UnmanagedType.LPWStr)]string typeName);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
delegate void CreateLazyTypeInfoDelegate(IntPtr typeInfo);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
delegate void LoadTypeInfoDelegate(IntPtr typeInfo);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
delegate void ReleaseNetReferenceDelegate(UInt64 objectId);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
delegate void ReleaseNetDelegateGCHandleDelegate(IntPtr handle);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
delegate IntPtr InstantiateTypeDelgate(IntPtr type);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
delegate void ReadPropertyDelegate(IntPtr property, IntPtr target, IntPtr indexParameter, IntPtr result);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
delegate void WritePropertyDelegate(IntPtr property, IntPtr target, IntPtr indexParameter, IntPtr value);
@ -124,20 +130,20 @@ namespace Qml.Net.Internal.Types
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
delegate void GCCollectDelegate(int maxGeneration);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
delegate bool RaiseNetSignalsDelegate(IntPtr target, [MarshalAs(UnmanagedType.LPWStr)]string signalName, IntPtr parameters);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
delegate void AwaitTaskDelegate(IntPtr target, IntPtr successCallback, IntPtr failureCallback);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
delegate bool SerializeDelegate(IntPtr instance, IntPtr result);
public CallbacksImpl(ICallbacks callbacks)
{
_callbacks = callbacks;
_isTypeValidDelegate = IsTypeValid;
GCHandle.Alloc(_isTypeValidDelegate);
@ -152,7 +158,7 @@ namespace Qml.Net.Internal.Types
_loadTypeInfoDelegate = LoadTypeInfo;
GCHandle.Alloc(_loadTypeInfoDelegate);
_instantiateTypeDelgate = InstantiateType;
GCHandle.Alloc(_instantiateTypeDelgate);
@ -182,7 +188,7 @@ namespace Qml.Net.Internal.Types
{
return _callbacks.IsTypeValid(typeName);
}
private void ReleaseNetReference(UInt64 objectId)
{
_callbacks.ReleaseNetReference(objectId);
@ -197,17 +203,17 @@ namespace Qml.Net.Internal.Types
{
_callbacks.CreateLazyTypeInfo(type);
}
private void LoadTypeInfo(IntPtr type)
{
_callbacks.LoadTypeInfo(type);
}
private IntPtr InstantiateType(IntPtr type)
{
return _callbacks.InstantiateType(type);
}
private void ReadProperty(IntPtr property, IntPtr target, IntPtr indexParameter, IntPtr result)
{
_callbacks.ReadProperty(property, target, indexParameter, result);
@ -228,7 +234,8 @@ namespace Qml.Net.Internal.Types
_callbacks.GCCollect(maxGeneration);
}
private bool RaiseNetSignals(IntPtr target,
private bool RaiseNetSignals(
IntPtr target,
string signalName,
IntPtr parameters)
{

View file

@ -8,7 +8,6 @@ namespace Qml.Net.Internal.Types
public NetDelegate(IntPtr handle)
: base(handle)
{
}
public static NetDelegate FromDelegate(Delegate del)
@ -22,7 +21,6 @@ namespace Qml.Net.Internal.Types
handle.Free();
}
public Delegate Delegate
{
get
@ -31,7 +29,7 @@ namespace Qml.Net.Internal.Types
return (Delegate)handle.Target;
}
}
protected override void DisposeUnmanaged(IntPtr ptr)
{
Interop.NetDelegate.Destroy(ptr);
@ -42,13 +40,17 @@ namespace Qml.Net.Internal.Types
{
[NativeSymbol(Entrypoint = "delegate_create")]
public CreateDel Create { get; set; }
public delegate IntPtr CreateDel(IntPtr handle);
[NativeSymbol(Entrypoint = "delegate_destroy")]
public DestroyDel Destroy { get; set; }
public delegate void DestroyDel(IntPtr del);
[NativeSymbol(Entrypoint = "delegate_getHandle")]
public GetHandleDel GetHandle { get; set; }
public delegate IntPtr GetHandleDel(IntPtr del);
}
}

View file

@ -1,33 +1,33 @@
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using Qml.Net.Internal;
namespace Qml.Net.Internal.Types
{
internal class NetMethodInfo : BaseDisposable
{
public NetMethodInfo(NetTypeInfo parentTypeInfo,
public NetMethodInfo(
NetTypeInfo parentTypeInfo,
string methodName,
NetTypeInfo returnTypeInfo,
bool isStatic)
: this(Create(parentTypeInfo, methodName, returnTypeInfo, isStatic))
{
}
public NetMethodInfo(IntPtr handle, bool ownsHandle = true)
:base(handle, ownsHandle)
: base(handle, ownsHandle)
{
}
private static IntPtr Create(NetTypeInfo parentTypeInfo,
private static IntPtr Create(
NetTypeInfo parentTypeInfo,
string methodName,
NetTypeInfo returnTypeInfo,
bool isStatic)
{
return Interop.NetMethodInfo.Create(parentTypeInfo?.Handle ?? IntPtr.Zero,
return Interop.NetMethodInfo.Create(
parentTypeInfo?.Handle ?? IntPtr.Zero,
methodName,
returnTypeInfo?.Handle ?? IntPtr.Zero,
isStatic);
@ -71,7 +71,7 @@ namespace Qml.Net.Internal.Types
}
return result;
}
protected override void DisposeUnmanaged(IntPtr ptr)
{
Interop.NetMethodInfo.Destroy(ptr);
@ -83,7 +83,6 @@ namespace Qml.Net.Internal.Types
public NetMethodInfoParameter(IntPtr handle)
: base(handle)
{
}
public string Name => Utilities.ContainerToString(Interop.NetMethodInfo.GetParameterName(Handle));
@ -97,57 +96,68 @@ namespace Qml.Net.Internal.Types
return new NetTypeInfo(result);
}
}
protected override void DisposeUnmanaged(IntPtr ptr)
{
Interop.NetMethodInfo.DestroyParameter(ptr);
}
}
internal class NetMethodInfoInterop
{
[NativeSymbol(Entrypoint = "method_info_parameter_destroy")]
public DestroyParameterDel DestroyParameter { get; set; }
public delegate void DestroyParameterDel(IntPtr parameter);
[NativeSymbol(Entrypoint = "method_info_parameter_getName")]
public GetParameterNameDel GetParameterName { get; set; }
public delegate IntPtr GetParameterNameDel(IntPtr methodParameter);
[NativeSymbol(Entrypoint = "method_info_parameter_getType")]
public GetParameterTypeDel GetParameterType { get; set; }
public delegate IntPtr GetParameterTypeDel(IntPtr methodParameter);
[NativeSymbol(Entrypoint = "method_info_create")]
public CreateDel Create { get; set; }
public delegate IntPtr CreateDel(IntPtr parentTypeInfo, [MarshalAs(UnmanagedType.LPWStr)]string methodName, IntPtr returnTypeInfo, bool isStatic);
[NativeSymbol(Entrypoint = "method_info_destroy")]
public DestroyDel Destroy { get; set; }
public delegate void DestroyDel(IntPtr methodInfo);
[NativeSymbol(Entrypoint = "method_info_getMethodName")]
public GetMethodNameDel GetMethodName { get; set; }
public delegate IntPtr GetMethodNameDel(IntPtr method);
[NativeSymbol(Entrypoint = "method_info_getReturnType")]
public GetReturnTypeDel GetReturnType { get; set; }
public delegate IntPtr GetReturnTypeDel(IntPtr method);
[NativeSymbol(Entrypoint = "method_info_isStatic")]
public GetIsStaticDel GetIsStatic { get; set; }
public delegate bool GetIsStaticDel(IntPtr method);
[NativeSymbol(Entrypoint = "method_info_addParameter")]
public AddParameterDel AddParameter { get; set; }
public delegate void AddParameterDel(IntPtr method, [MarshalAs(UnmanagedType.LPWStr)]string name, IntPtr type);
[NativeSymbol(Entrypoint = "method_info_getParameterCount")]
public GetParameterCountDel GetParameterCount { get; set; }
public delegate int GetParameterCountDel(IntPtr method);
[NativeSymbol(Entrypoint = "method_info_getParameter")]
public GetParameterDel GetParameter { get; set; }
public delegate IntPtr GetParameterDel(IntPtr method, int index);
}
}

View file

@ -1,41 +1,42 @@
using System;
using System.Runtime.InteropServices;
using Qml.Net.Internal;
namespace Qml.Net.Internal.Types
{
internal class NetPropertyInfo : BaseDisposable
{
public NetPropertyInfo(NetTypeInfo parentType,
public NetPropertyInfo(
NetTypeInfo parentType,
string name,
NetTypeInfo returnType,
bool canRead,
bool canWrite,
NetSignalInfo notifySignal)
: this(Create(parentType,
: this(Create(
parentType,
name,
returnType,
canRead,
canWrite,
notifySignal))
{
}
public NetPropertyInfo(IntPtr handle, bool ownsHandle = true)
: base(handle, ownsHandle)
{
}
private static IntPtr Create(NetTypeInfo parentType,
private static IntPtr Create(
NetTypeInfo parentType,
string name,
NetTypeInfo returnType,
bool canRead,
bool canWrite,
NetSignalInfo notifySignal)
{
return Interop.NetPropertyInfo.Create(parentType?.Handle ?? IntPtr.Zero,
return Interop.NetPropertyInfo.Create(
parentType?.Handle ?? IntPtr.Zero,
name,
returnType?.Handle ?? IntPtr.Zero,
canRead,
@ -46,7 +47,7 @@ namespace Qml.Net.Internal.Types
public NetTypeInfo ParentType => new NetTypeInfo(Interop.NetPropertyInfo.GetParentType(Handle));
public string Name => Utilities.ContainerToString(Interop.NetPropertyInfo.GetPropertyName(Handle));
public NetTypeInfo ReturnType => new NetTypeInfo(Interop.NetPropertyInfo.GetReturnType(Handle));
public bool CanRead => Interop.NetPropertyInfo.GetCanRead(Handle);
@ -60,12 +61,13 @@ namespace Qml.Net.Internal.Types
var result = Interop.NetPropertyInfo.GetNotifySignal(Handle);
return result == IntPtr.Zero ? null : new NetSignalInfo(result);
}
set
{
Interop.NetPropertyInfo.SetNotifySignal(Handle, value.Handle);
}
}
protected override void DisposeUnmanaged(IntPtr ptr)
{
Interop.NetPropertyInfo.Destroy(ptr);
@ -76,43 +78,53 @@ namespace Qml.Net.Internal.Types
{
[NativeSymbol(Entrypoint = "property_info_create")]
public CreateDel Create { get; set; }
public delegate IntPtr CreateDel(IntPtr parentType,
public delegate IntPtr CreateDel(
IntPtr parentType,
[MarshalAs(UnmanagedType.LPWStr)]string methodName,
IntPtr returnType,
bool canRead,
bool canWrite,
IntPtr notifySignal);
[NativeSymbol(Entrypoint = "property_info_destroy")]
public DestroyDel Destroy { get; set; }
public delegate void DestroyDel(IntPtr property);
[NativeSymbol(Entrypoint = "property_info_getParentType")]
public GetParentTypeDel GetParentType { get; set; }
public delegate IntPtr GetParentTypeDel(IntPtr property);
[NativeSymbol(Entrypoint = "property_info_getPropertyName")]
public GetPropertyNameDel GetPropertyName { get; set; }
public delegate IntPtr GetPropertyNameDel(IntPtr property);
[NativeSymbol(Entrypoint = "property_info_getReturnType")]
public GetReturnTypeDel GetReturnType { get; set; }
public delegate IntPtr GetReturnTypeDel(IntPtr property);
[NativeSymbol(Entrypoint = "property_info_canRead")]
public GetCanReadDel GetCanRead { get; set; }
public delegate bool GetCanReadDel(IntPtr property);
[NativeSymbol(Entrypoint = "property_info_canWrite")]
public GetCanWriteDel GetCanWrite { get; set; }
public delegate bool GetCanWriteDel(IntPtr property);
[NativeSymbol(Entrypoint = "property_info_getNotifySignal")]
public GetNotifySignalDel GetNotifySignal { get; set; }
public delegate IntPtr GetNotifySignalDel(IntPtr property);
[NativeSymbol(Entrypoint = "property_info_setNotifySignal")]
public SetNotifySignalDel SetNotifySignal { get; set; }
public delegate void SetNotifySignalDel(IntPtr property, IntPtr signal);
}
}

View file

@ -1,7 +1,6 @@
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using Qml.Net.Internal;
using Qml.Net.Internal.Qml;
namespace Qml.Net.Internal.Types
@ -9,21 +8,20 @@ namespace Qml.Net.Internal.Types
internal class NetReference : BaseDisposable
{
private NetReference(UInt64 objectId, NetTypeInfo type, bool ownsHandle = true)
:base(Interop.NetReference.Create(objectId, type.Handle), ownsHandle)
: base(Interop.NetReference.Create(objectId, type.Handle), ownsHandle)
{
}
public NetReference(IntPtr handle, bool ownsHandle = true)
: base(handle, ownsHandle)
{
}
public object Instance
{
get
{
if(ObjectIdReferenceTracker.TryGetObjectFor(ObjectId, out var obj))
if (ObjectIdReferenceTracker.TryGetObjectFor(ObjectId, out var obj))
{
return obj;
}
@ -60,9 +58,9 @@ namespace Qml.Net.Internal.Types
{
Interop.NetReference.Destroy(ptr);
}
#region Instance helpers
private static Type GetUnproxiedType(Type type)
{
if (type.Namespace == "Castle.Proxies")
@ -70,7 +68,7 @@ namespace Qml.Net.Internal.Types
return type;
}
public static NetReference CreateForObject(object value, bool autoCreateIfNotExist = true)
{
if (value == null) return null;
@ -81,10 +79,13 @@ namespace Qml.Net.Internal.Types
// This item isn't tagged, so don't auto tag.
return null;
}
var typeInfo = NetTypeManager.GetTypeInfo(GetUnproxiedType(value.GetType()));
if(typeInfo == null) throw new InvalidOperationException($"Couldn't create type info from {value.GetType().AssemblyQualifiedName}");
var typeInfo = NetTypeManager.GetTypeInfo(GetUnproxiedType(value.GetType()));
if (typeInfo == null)
{
throw new InvalidOperationException($"Couldn't create type info from {value.GetType().AssemblyQualifiedName}");
}
objectId = value.GetOrCreateTag();
var newNetReference = new NetReference(objectId.Value, typeInfo);
@ -102,25 +103,30 @@ namespace Qml.Net.Internal.Types
}
internal class NetReferenceInterop
{
{
[NativeSymbol(Entrypoint = "net_instance_create")]
public CreateDel Create { get; set; }
public delegate IntPtr CreateDel(UInt64 objectId, IntPtr type);
[NativeSymbol(Entrypoint = "net_instance_destroy")]
public DestroyDel Destroy { get; set; }
public delegate void DestroyDel(IntPtr instance);
[NativeSymbol(Entrypoint = "net_instance_clone")]
public CloneDel Clone { get; set; }
public delegate IntPtr CloneDel(IntPtr instance);
[NativeSymbol(Entrypoint = "net_instance_getObjectId")]
public GetObjectIdDel GetObjectId { get; set; }
public delegate UInt64 GetObjectIdDel(IntPtr instance);
[NativeSymbol(Entrypoint = "net_instance_activateSignal")]
public ActivateSignalDel ActivateSignal { get; set; }
public delegate bool ActivateSignalDel(IntPtr instance, [MarshalAs(UnmanagedType.LPWStr)]string signalName, IntPtr variants);
}
@ -129,6 +135,7 @@ namespace Qml.Net.Internal.Types
class ObjectEntry
{
public object Obj { get; private set; }
public UInt64 Counter { get; set; }
public ObjectEntry(object obj, UInt64 count)
@ -143,9 +150,9 @@ namespace Qml.Net.Internal.Types
internal static bool TryGetObjectFor(UInt64 objectId, out object obj)
{
lock(_LockObject)
lock (_LockObject)
{
if(_ObjectIdObjectLookup.ContainsKey(objectId))
if (_ObjectIdObjectLookup.ContainsKey(objectId))
{
obj = _ObjectIdObjectLookup[objectId].Obj;
return true;
@ -164,13 +171,16 @@ namespace Qml.Net.Internal.Types
throw new InvalidOperationException("Releasing a NetReference that hasn't been counted!");
}
_ObjectIdObjectLookup[objectId].Counter--;
//when there are no more QML references
// When there are no more QML references.
if (_ObjectIdObjectLookup[objectId].Counter == 0)
{
var obj = _ObjectIdObjectLookup[objectId].Obj;
//remove object entry
// Remove object entry.
_ObjectIdObjectLookup.Remove(objectId);
//and notify the behaviors
// And notify the behaviors.
InteropBehaviors.OnObjectLeavesNative(obj, objectId);
}
}

View file

@ -8,19 +8,17 @@ namespace Qml.Net.Internal.Types
internal NetSignalInfo(IntPtr handle, bool ownsHandle = true)
: base(handle, ownsHandle)
{
}
public NetSignalInfo(NetTypeInfo parentType, string name)
: this(Interop.NetSignalInfo.Create(parentType.Handle, name))
{
}
public NetTypeInfo ParentType => new NetTypeInfo(Interop.NetSignalInfo.GetParentType(Handle));
public string Name => Utilities.ContainerToString(Interop.NetSignalInfo.GetName(Handle));
public void AddParameter(NetVariantType type)
{
Interop.NetSignalInfo.AddParameter(Handle, type);
@ -43,26 +41,37 @@ namespace Qml.Net.Internal.Types
{
[NativeSymbol(Entrypoint = "signal_info_create")]
public CreateDel Create { get; set; }
public delegate IntPtr CreateDel(IntPtr parentType, [MarshalAs(UnmanagedType.LPWStr)] string name);
[NativeSymbol(Entrypoint = "signal_info_destroy")]
public DestroyDel Destroy { get; set; }
public delegate void DestroyDel(IntPtr signal);
[NativeSymbol(Entrypoint = "signal_info_getParentType")]
public GetParentTypeDel GetParentType { get; set; }
public delegate IntPtr GetParentTypeDel(IntPtr signal);
[NativeSymbol(Entrypoint = "signal_info_getName")]
public GetNameDel GetName { get; set; }
public delegate IntPtr GetNameDel(IntPtr signal);
[NativeSymbol(Entrypoint = "signal_info_addParameter")]
public AddParameterDel AddParameter { get; set; }
public delegate void AddParameterDel(IntPtr signal, NetVariantType type);
[NativeSymbol(Entrypoint = "signal_info_getParameterCount")]
public GetParameterCountDel GetParameterCount { get; set; }
public delegate int GetParameterCountDel(IntPtr signal);
[NativeSymbol(Entrypoint = "signal_info_getParameter")]
public GetParameterDel GetParameter { get; set; }
public delegate NetVariantType GetParameterDel(IntPtr signal, int index);
}
}

View file

@ -6,14 +6,13 @@ namespace Qml.Net.Internal.Types
internal class NetTypeInfo : BaseDisposable
{
public NetTypeInfo(string fullTypeName)
:this(Interop.NetTypeInfo.Create(fullTypeName))
: this(Interop.NetTypeInfo.Create(fullTypeName))
{
}
public NetTypeInfo(IntPtr handle, bool ownsHandle = true)
:base(handle, ownsHandle)
: base(handle, ownsHandle)
{
}
public string FullTypeName => Utilities.ContainerToString(Interop.NetTypeInfo.GetFullTypeName(Handle));
@ -35,13 +34,13 @@ namespace Qml.Net.Internal.Types
get => Interop.NetTypeInfo.GetIsArray(Handle);
set => Interop.NetTypeInfo.SetIsArray(Handle, value);
}
public bool IsList
{
get => Interop.NetTypeInfo.GetIsList(Handle);
set => Interop.NetTypeInfo.SetIsList(Handle, value);
}
public void AddMethod(NetMethodInfo methodInfo)
{
Interop.NetTypeInfo.AddMethod(Handle, methodInfo.Handle);
@ -55,7 +54,7 @@ namespace Qml.Net.Internal.Types
if (result == IntPtr.Zero) return null;
return new NetMethodInfo(result);
}
public int LocalMethodCount => Interop.NetTypeInfo.GetLocalMethodCount(Handle);
public NetMethodInfo GetLocalMethod(int index)
@ -64,7 +63,7 @@ namespace Qml.Net.Internal.Types
if (result == IntPtr.Zero) return null;
return new NetMethodInfo(result);
}
public int StaticMethodCount => Interop.NetTypeInfo.GetStaticMethodCount(Handle);
public NetMethodInfo GetStaticMethod(int index)
@ -73,7 +72,7 @@ namespace Qml.Net.Internal.Types
if (result == IntPtr.Zero) return null;
return new NetMethodInfo(result);
}
public void AddProperty(NetPropertyInfo property)
{
Interop.NetTypeInfo.AddProperty(Handle, property.Handle);
@ -87,7 +86,7 @@ namespace Qml.Net.Internal.Types
if (result == IntPtr.Zero) return null;
return new NetPropertyInfo(result);
}
public void AddSignal(NetSignalInfo signal)
{
Interop.NetTypeInfo.AddSignal(Handle, signal.Handle);
@ -110,7 +109,7 @@ namespace Qml.Net.Internal.Types
{
Interop.NetTypeInfo.EnsureLoaded(Handle);
}
protected override void DisposeUnmanaged(IntPtr ptr)
{
Interop.NetTypeInfo.Destroy(ptr);
@ -121,110 +120,137 @@ namespace Qml.Net.Internal.Types
{
[NativeSymbol(Entrypoint = "type_info_create")]
public CreateDel Create { get; set; }
public delegate IntPtr CreateDel([MarshalAs(UnmanagedType.LPWStr)]string fullTypeName);
[NativeSymbol(Entrypoint = "type_info_destroy")]
public DestroyDel Destroy { get; set; }
public delegate void DestroyDel(IntPtr netTypeInfo);
[NativeSymbol(Entrypoint = "type_info_getFullTypeName")]
public GetFullTypeNameDel GetFullTypeName { get; set; }
public delegate IntPtr GetFullTypeNameDel(IntPtr netTypeInfo);
[NativeSymbol(Entrypoint = "type_info_setClassName")]
public SetClassNameDel SetClassName { get; set; }
public delegate void SetClassNameDel(IntPtr netTypeInfo, [MarshalAs(UnmanagedType.LPWStr)]string className);
[NativeSymbol(Entrypoint = "type_info_getClassName")]
public GetClassNameDel GetClassName { get; set; }
public delegate IntPtr GetClassNameDel(IntPtr netTypeInfo);
[NativeSymbol(Entrypoint = "type_info_setPrefVariantType")]
public SetPrefVariantTypeDel SetPrefVariantType { get; set; }
public delegate void SetPrefVariantTypeDel(IntPtr netTypeInfo, NetVariantType variantType);
[NativeSymbol(Entrypoint = "type_info_getPrefVariantType")]
public GetPrefVariantTypeDel GetPrefVariantType { get; set; }
public delegate NetVariantType GetPrefVariantTypeDel(IntPtr netTypeInfo);
[NativeSymbol(Entrypoint = "type_info_setIsArray")]
public GetIsArrayDel GetIsArray { get; set; }
public delegate bool GetIsArrayDel(IntPtr netTypeInfo);
[NativeSymbol(Entrypoint = "type_info_getIsArray")]
public SetIsArrayDel SetIsArray { get; set; }
public delegate void SetIsArrayDel(IntPtr netTypeInfo, bool isArray);
[NativeSymbol(Entrypoint = "type_info_setIsList")]
public GetIsListDel GetIsList { get; set; }
public delegate bool GetIsListDel(IntPtr netTypeInfo);
[NativeSymbol(Entrypoint = "type_info_getIsList")]
public SetIsListDel SetIsList { get; set; }
public delegate void SetIsListDel(IntPtr netTypeInfo, bool isList);
[NativeSymbol(Entrypoint = "type_info_addMethod")]
public AddMethodDel AddMethod { get; set; }
public delegate void AddMethodDel(IntPtr typeInfo, IntPtr methodInfo);
[NativeSymbol(Entrypoint = "type_info_getMethodCount")]
public GetMethodCountDel GetMethodCount { get; set; }
public delegate int GetMethodCountDel(IntPtr typeInfo);
[NativeSymbol(Entrypoint = "type_info_getMethodInfo")]
public GetMethodInfoDel GetMethodInfo { get; set; }
public delegate IntPtr GetMethodInfoDel(IntPtr typeInfo, int index);
[NativeSymbol(Entrypoint = "type_info_getLocalMethodCount")]
public GetLocalMethodCountDel GetLocalMethodCount { get; set; }
public delegate int GetLocalMethodCountDel(IntPtr typeInfo);
[NativeSymbol(Entrypoint = "type_info_getLocalMethodInfo")]
public GetLocalMethodInfoDel GetLocalMethodInfo { get; set; }
public delegate IntPtr GetLocalMethodInfoDel(IntPtr typeInfo, int index);
[NativeSymbol(Entrypoint = "type_info_getStaticMethodCount")]
public GetStaticMethodCountDel GetStaticMethodCount { get; set; }
public delegate int GetStaticMethodCountDel(IntPtr typeInfo);
[NativeSymbol(Entrypoint = "type_info_getStaticMethodInfo")]
public GetStaticMethodInfoDel GetStaticMethodInfo { get; set; }
public delegate IntPtr GetStaticMethodInfoDel(IntPtr typeInfo, int index);
[NativeSymbol(Entrypoint = "type_info_addProperty")]
public AddPropertyDel AddProperty { get; set; }
public delegate void AddPropertyDel(IntPtr typeInfo, IntPtr property);
[NativeSymbol(Entrypoint = "type_info_getPropertyCount")]
public GetPropertyCountDel GetPropertyCount { get; set; }
public delegate int GetPropertyCountDel(IntPtr typeInfo);
[NativeSymbol(Entrypoint = "type_info_getProperty")]
public GetPropertyDel GetProperty { get; set; }
public delegate IntPtr GetPropertyDel(IntPtr typeInfo, int index);
[NativeSymbol(Entrypoint = "type_info_addSignal")]
public AddSignalDel AddSignal { get; set; }
public delegate void AddSignalDel(IntPtr typeInfo, IntPtr signal);
[NativeSymbol(Entrypoint = "type_info_getSignalCount")]
public GetSignalCountDel GetSignalCount { get; set; }
public delegate int GetSignalCountDel(IntPtr typeInfo);
[NativeSymbol(Entrypoint = "type_info_getSignal")]
public GetSignalDel GetSignal { get; set; }
public delegate IntPtr GetSignalDel(IntPtr typeInfo, int index);
[NativeSymbol(Entrypoint = "type_info_isLoaded")]
public IsLoadedDel IsLoaded { get; set; }
public delegate bool IsLoadedDel(IntPtr typeInfo);
[NativeSymbol(Entrypoint = "type_info_isLoading")]
public IsLoadingDel IsLoading { get; set; }
public delegate bool IsLoadingDel(IntPtr typeInfo);
[NativeSymbol(Entrypoint = "type_info_ensureLoaded")]
public EnsureLoadedDel EnsureLoaded { get; set; }
public delegate void EnsureLoadedDel(IntPtr typeInfo);
}
}

View file

@ -12,7 +12,7 @@ namespace Qml.Net.Internal.Types
public static NetTypeInfo GetTypeInfo(Type type)
{
if(type == null)
if (type == null)
{
return null;
}
@ -21,11 +21,12 @@ namespace Qml.Net.Internal.Types
return netTypeInfo;
}
}
internal class NetTypeManagerInterop
{
[NativeSymbol(Entrypoint = "type_manager_getTypeInfo")]
public GetTypeInfoDel GetTypeInfo { get; set; }
public delegate IntPtr GetTypeInfoDel([MarshalAs(UnmanagedType.LPWStr)]string fullTypeName);
}
}

View file

@ -18,7 +18,7 @@ namespace Qml.Net.Internal
{
var result = _original.Resolve(library);
if(!result.IsSuccess && library == "QmlNet")
if (!result.IsSuccess && library == "QmlNet")
{
// Try to let .NET load the library.
try
@ -34,7 +34,7 @@ namespace Qml.Net.Internal
var path = Marshal.PtrToStringAnsi(bytes);
Marshal.FreeHGlobal(bytes);
if(File.Exists(path))
if (File.Exists(path))
{
return ResolvePathResult.FromSuccess(path);
}

View file

@ -7,14 +7,13 @@ namespace Qml.Net
{
public NotifySignalAttribute()
{
}
public NotifySignalAttribute(string name)
{
Name = name;
}
public string Name { get; set; }
}
}

View file

@ -15,31 +15,30 @@ namespace Qml.Net
readonly SynchronizationContext _oldSynchronizationContext;
public QGuiApplication()
:this(null)
: this(null)
{
}
public QGuiApplication(string[] args)
:base(Create(args?.ToList()))
: base(Create(args?.ToList()))
{
TriggerDelegate triggerDelegate = Trigger;
_triggerHandle = GCHandle.Alloc(triggerDelegate);
Interop.QGuiApplication.AddTriggerCallback(Handle, Marshal.GetFunctionPointerForDelegate(triggerDelegate));
_oldSynchronizationContext = SynchronizationContext.Current;
SynchronizationContext.SetSynchronizationContext(new QtSynchronizationContext(this));
}
internal QGuiApplication(IntPtr existingApp)
:base(CreateFromExisting(existingApp))
: base(CreateFromExisting(existingApp))
{
TriggerDelegate triggerDelegate = Trigger;
_triggerHandle = GCHandle.Alloc(triggerDelegate);
Interop.QGuiApplication.AddTriggerCallback(Handle, Marshal.GetFunctionPointerForDelegate(triggerDelegate));
_oldSynchronizationContext = SynchronizationContext.Current;
SynchronizationContext.SetSynchronizationContext(new QtSynchronizationContext(this));
}
@ -84,7 +83,7 @@ namespace Qml.Net
}
action?.Invoke();
}
protected override void DisposeUnmanaged(IntPtr ptr)
{
SynchronizationContext.SetSynchronizationContext(_oldSynchronizationContext);
@ -103,7 +102,7 @@ namespace Qml.Net
{
args = new List<string>();
}
// By default, the argv[0] should be the process name.
// .NET doesn't pass that name, but Qt should get it
// since it does in a normal Qt environment.
@ -119,13 +118,14 @@ namespace Qml.Net
strings.Add(variant);
}
}
return Interop.QGuiApplication.Create(strings.Handle, IntPtr.Zero);
}
}
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
private delegate void TriggerDelegate();
private class QtSynchronizationContext : SynchronizationContext
{
readonly QGuiApplication _guiApp;
@ -141,35 +141,42 @@ namespace Qml.Net
}
}
}
internal class QGuiApplicationInterop
{
[NativeSymbol(Entrypoint = "qguiapplication_create")]
public CreateDel Create { get; set; }
public delegate IntPtr CreateDel(IntPtr args, IntPtr existingApp);
[NativeSymbol(Entrypoint = "qguiapplication_destroy")]
public DestroyDel Destroy { get; set; }
public delegate void DestroyDel(IntPtr app);
[NativeSymbol(Entrypoint = "qguiapplication_exec")]
public ExecDel Exec { get; set; }
public delegate int ExecDel();
[NativeSymbol(Entrypoint = "qguiapplication_addTriggerCallback")]
public AddTriggerCallbackDel AddTriggerCallback { get; set; }
public delegate void AddTriggerCallbackDel(IntPtr app, IntPtr callback);
[NativeSymbol(Entrypoint = "qguiapplication_requestTrigger")]
public RequestTriggerDel RequestTrigger { get; set; }
public delegate void RequestTriggerDel(IntPtr app);
[NativeSymbol(Entrypoint = "qguiapplication_exit")]
public ExitDel Exit { get; set; }
public delegate void ExitDel(int returnCode);
[NativeSymbol(Entrypoint = "qguiapplication_internalPointer")]
public InternalPointerDel InternalPointer { get; set; }
public delegate IntPtr InternalPointerDel(IntPtr app);
}
}

View file

@ -10,15 +10,13 @@ namespace Qml.Net
public sealed class QQmlApplicationEngine : BaseDisposable
{
public QQmlApplicationEngine()
:base(Interop.QQmlApplicationEngine.Create(IntPtr.Zero))
: base(Interop.QQmlApplicationEngine.Create(IntPtr.Zero))
{
}
internal QQmlApplicationEngine(IntPtr existingEngine)
:base(Interop.QQmlApplicationEngine.Create(existingEngine))
: base(Interop.QQmlApplicationEngine.Create(existingEngine))
{
}
public void Load(string path)
@ -30,7 +28,7 @@ namespace Qml.Net
{
Interop.QQmlApplicationEngine.LoadData(Handle, data);
}
public void AddImportPath(string path)
{
Interop.QQmlApplicationEngine.AddImportPath(Handle, path);
@ -67,7 +65,7 @@ namespace Qml.Net
}
}
}
internal IntPtr InternalPointer => Interop.QQmlApplicationEngine.InternalPointer(Handle);
[Obsolete("Use Qml.RegisterType<T>() instead.", true)]
@ -85,8 +83,8 @@ namespace Qml.Net
/// Activates the MVVM behavior.
/// This Behavior automatically connects INotifyPropertyChanged instances with appropriate signals on the QML side
/// and triggers those signals whenever the PropertyChanged event of the INotifyPropertyChanged instances is triggered.
///
/// Call this before any INotifyPropertyChanged type is registered!
///
/// Call this before any INotifyPropertyChanged type is registered!
/// Otherwise the behavior might not include
/// INotifyPropertyChanged types that were registered (implicitly or explicitly) before this call
/// </summary>
@ -100,51 +98,62 @@ namespace Qml.Net
Interop.QQmlApplicationEngine.Destroy(ptr);
}
}
internal class QQmlApplicationEngineInterop
{
[NativeSymbol(Entrypoint = "qqmlapplicationengine_create")]
public CreateDel Create { get; set; }
public delegate IntPtr CreateDel(IntPtr existingEngine);
[NativeSymbol(Entrypoint = "qqmlapplicationengine_destroy")]
public DestroyDel Destroy { get; set; }
public delegate void DestroyDel(IntPtr engine);
[NativeSymbol(Entrypoint = "qqmlapplicationengine_load")]
public LoadDel Load { get; set; }
public delegate int LoadDel(IntPtr engine, [MarshalAs(UnmanagedType.LPWStr)]string path);
[NativeSymbol(Entrypoint = "qqmlapplicationengine_loadData")]
public LoadDataDel LoadData { get; set; }
public delegate int LoadDataDel(IntPtr engine, [MarshalAs(UnmanagedType.LPWStr)]string path);
[NativeSymbol(Entrypoint = "qqmlapplicationengine_registerType")]
public RegisterTypeDel RegisterType { get; set; }
public delegate int RegisterTypeDel(IntPtr type, [MarshalAs(UnmanagedType.LPWStr)]string uri, int versionMajor, int versionMinor, [MarshalAs(UnmanagedType.LPWStr)]string qmlName);
[NativeSymbol(Entrypoint = "qqmlapplicationengine_registerSingletonTypeQml")]
public RegisterSingletonTypeQmlDel RegisterSingletonTypeQml { get; set; }
public delegate int RegisterSingletonTypeQmlDel([MarshalAs(UnmanagedType.LPWStr)]string url, [MarshalAs(UnmanagedType.LPWStr)]string uri, int versionMajor, int versionMinor, [MarshalAs(UnmanagedType.LPWStr)]string qmlName);
[NativeSymbol(Entrypoint = "qqmlapplicationengine_registerSingletonTypeNet")]
public RegisterSingletonTypeNetDel RegisterSingletonTypeNet { get; set; }
public delegate int RegisterSingletonTypeNetDel(IntPtr type, [MarshalAs(UnmanagedType.LPWStr)]string uri, int versionMajor, int versionMinor, [MarshalAs(UnmanagedType.LPWStr)]string typeName);
[NativeSymbol(Entrypoint = "qqmlapplicationengine_addImportPath")]
public AddImportPathDel AddImportPath { get; set; }
public delegate void AddImportPathDel(IntPtr engine, [MarshalAs(UnmanagedType.LPWStr)]string path);
[NativeSymbol(Entrypoint = "qqmlapplicationengine_internalPointer")]
public InternalPointerDel InternalPointer { get; set; }
public delegate IntPtr InternalPointerDel(IntPtr app);
[NativeSymbol(Entrypoint = "qqmlapplicationengine_getContextProperty")]
public GetContextPropertyDel GetContextProperty { get; set; }
public delegate IntPtr GetContextPropertyDel(IntPtr app, [MarshalAs(UnmanagedType.LPWStr)]string name);
[NativeSymbol(Entrypoint = "qqmlapplicationengine_setContextProperty")]
public SetContextPropertyDel SetContextProperty { get; set; }
public delegate void SetContextPropertyDel(IntPtr app, [MarshalAs(UnmanagedType.LPWStr)]string path, IntPtr value);
}
}

View file

@ -15,15 +15,17 @@ namespace Qml.Net
Interop.QQuickStyle.SetStyle(style);
}
}
internal class QQuickStyleInterop
{
[NativeSymbol(Entrypoint = "qquickstyle_setFallbackStyle")]
public SetFallbackStyleDel SetFallbackStyle { get; set; }
public delegate void SetFallbackStyleDel([MarshalAs(UnmanagedType.LPWStr)]string style);
[NativeSymbol(Entrypoint = "qquickstyle_setStyle")]
public SetStyleDel SetStyle { get; set; }
public delegate void SetStyleDel([MarshalAs(UnmanagedType.LPWStr)]string style);
}
}

View file

@ -15,14 +15,17 @@ namespace Qml.Net
return Internal.Interop.QResource.UnregisterResource(rccFileName, resourceRoot);
}
}
internal class QResourceInterop
{
[NativeSymbol(Entrypoint = "qresource_registerResource")]
public RegisterResourceDel RegisterResource { get; set; }
public delegate bool RegisterResourceDel([MarshalAs(UnmanagedType.LPWStr)]string rccFileName, [MarshalAs(UnmanagedType.LPWStr)]string resourceRoot);
[NativeSymbol(Entrypoint = "qresource_unregisterResource")]
public UnregisterResourceDel UnregisterResource { get; set; }
public delegate bool UnregisterResourceDel([MarshalAs(UnmanagedType.LPWStr)]string rccFileName, [MarshalAs(UnmanagedType.LPWStr)]string resourceRoot);
}
}

View file

@ -1,10 +1,12 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<CodeAnalysisRuleSet>../../../StyleCop.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.CSharp" Version="4.5.0" />
<PackageReference Include="NetNativeLibLoader" Version="0.1.0" />
<PackageReference Include="Newtonsoft.Json" Version="12.0.1" />
<PackageReference Include="StyleCop.Analyzers" Version="1.0.2" />
</ItemGroup>
</Project>

View file

@ -15,7 +15,7 @@ namespace Qml.Net
{
return Interop.QQmlApplicationEngine.RegisterSingletonTypeQml(url, uri, versionMajor, versionMinor, qmlName);
}
public static int RegisterSingletonType<T>(string uri, int versionMajor = 1, int versionMinor = 0)
{
using (var type = NetTypeManager.GetTypeInfo<T>())

View file

@ -1,6 +1,6 @@
using Qml.Net.Internal;
using System;
using System;
using System.Runtime.InteropServices;
using Qml.Net.Internal;
namespace Qml.Net
{
@ -26,12 +26,17 @@ namespace Qml.Net
{
[NativeSymbol(Entrypoint = "qt_putenv")]
public PutEnvDel PutEnv { get; set; }
public delegate bool PutEnvDel([MarshalAs(UnmanagedType.LPStr)]string name, [MarshalAs(UnmanagedType.LPStr)]string value);
[NativeSymbol(Entrypoint = "qt_getenv")]
public GetEnvDel GetEnv { get; set; }
public delegate IntPtr GetEnvDel(string name);
[NativeSymbol(Entrypoint = "qt_version")]
public QtVersionDel QtVersion { get; set; }
public delegate IntPtr QtVersionDel();
}
}

View file

@ -9,11 +9,12 @@ namespace Qml.Net
Interop.QtWebEngine.Initialize();
}
}
internal class QtWebEngineInterop
{
[NativeSymbol(Entrypoint = "qtwebebengine_initialize")]
public InitializeDel Initialize { get; set; }
public delegate void InitializeDel();
}
}

View file

@ -9,7 +9,7 @@ namespace Qml.Net.Serialization
{
ContractResolver = new CamelCasePropertyNamesContractResolver()
};
public string Serialize(object value)
{
return JsonConvert.SerializeObject(value, _defaultSerializerSettings);

View file

@ -10,10 +10,9 @@ namespace Qml.Net
Name = name;
Parameters = parameters;
}
public string Name { get; }
public NetVariantType[] Parameters { get; }
}
}

View file

@ -23,17 +23,17 @@ namespace Qml.Net
}
var signals = instance.GetAttachedDelegates(signalName);
if (signals == null || signals.Count <= 0)
{
return false;
}
foreach (var del in signals)
{
del.DynamicInvoke(args);
}
return true;
}

View file

@ -34,7 +34,7 @@ namespace Qml.Net
{
_func = func;
}
public object Create(Type type)
{
return _func(type);

View file

@ -24,13 +24,14 @@ namespace Qml.Net
{
private readonly IntPtr _ignore;
public readonly IntPtr Data;
}
}
}
internal class UtilitiesInterop
{
[NativeSymbol(Entrypoint = "freeString")]
public FreeStringDel FreeString { get; set; }
public delegate void FreeStringDel(IntPtr container);
}
}