Skip to content
Merged

sync #496

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -108,4 +108,6 @@
/CSharpBible/MVVM_Tutorial/UWP_00_Test/AppPackages
/TestStatements/TestStatements/Version.inc
obj.net
/JC-AMS/Core/Resource/Version.inc
/TestStatements/*.snk
/CSharpBible/Libraries/*.snk
5 changes: 4 additions & 1 deletion TestStatements/AppWithPlugin/AppWithPlugin.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,18 @@
</ImportGroup>
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFrameworks>net6.0;net7.0;net8.0;net9.0</TargetFrameworks>
<TargetFrameworks>net481; net6.0;net7.0;net8.0;net9.0</TargetFrameworks>
<Nullable>enable</Nullable>
<UserSecretsId>85d7cf50-cf51-4539-ba76-0a882d37b3ec</UserSecretsId>
</PropertyGroup>
<Import Sdk="Microsoft.NET.Sdk" Project="Sdk.props" />
<Import Sdk="Microsoft.NET.Sdk" Project="Sdk.targets" />
<ItemGroup>
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.4.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.UserSecrets" Version="9.0.0" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="9.0.0" />
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="9.0.0" />
<PackageReference Include="System.Runtime.Loader" Version="4.3.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\PluginBase\PluginBase.csproj" />
Expand Down
61 changes: 49 additions & 12 deletions TestStatements/AppWithPlugin/Model/AppWithPlugin.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,33 @@ static Assembly LoadPlugin(string relativePath)
string pluginLocation = Path.GetFullPath(Path.Combine(root, relativePath.Replace('\\', Path.DirectorySeparatorChar),"Debug", "net6.0"));
Console.WriteLine($"Loading commands from: {pluginLocation}");
PluginLoadContext loadContext = new PluginLoadContext(pluginLocation);
return loadContext.LoadFromAssemblyPath(Path.Combine(pluginLocation,relativePath)+".dll");
string assemblyPath = Path.Combine(pluginLocation, relativePath) + ".dll";
Assembly assembly = loadContext.LoadFromAssemblyPath(assemblyPath);
if (!assembly?.IsFullyTrusted ?? false)
return null;

// Additional check for a valid signature (if applicable)
if (!IsAssemblySigned(assembly))
{
Console.WriteLine("Assembly is not signed or has an invalid signature.");
return null;
}
return assembly;
}

static bool IsAssemblySigned(Assembly assembly)
{
try
{
var name = assembly.GetName();
var publicKey = name.GetPublicKey();
var hash = assembly.GetHashCode(); // 30015890
return publicKey != null && publicKey.Length > 0;
}
catch
{
return false;
}
}

static IEnumerable<ICommand> CreateCommands(Assembly assembly,IEnvironment env)
Expand Down Expand Up @@ -59,18 +85,19 @@ static IEnumerable<ICommand> CreateCommands(Assembly assembly,IEnvironment env)
IEnumerable<ICommand>? commands;
private IMessenger? _messanger;
private IServiceProvider? _sp;
private IServiceCollection? _sc;

public IData data { get => throw new NotImplementedException(); }
public IUserInterface ui { get => this; }
public IMessenger messaging { get => _messanger ?? new WeakReferenceMessenger(); }
public string Title { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
public string Title { get => Console.Title; set => Console.Title = value; }

public void Initialize(string[] args)
{
_sp = new ServiceCollection()
.AddTransient<IRandom, Model.Random>()
.AddTransient<ISysTime, Model.SysTime>()
.AddSingleton<ILogger, Logging>()
_sp = (_sc=(_sc ?? new ServiceCollection())
.AddTransient<IRandom, Random>()
.AddTransient<ISysTime, SysTime>()
.AddSingleton<ILogger, Logging>())
.BuildServiceProvider();


Expand All @@ -80,10 +107,10 @@ public void Initialize(string[] args)
];

commands = pluginPaths.SelectMany(pluginPath =>
{
Assembly pluginAssembly = LoadPlugin(pluginPath);
return CreateCommands(pluginAssembly,this);
}).ToList();
{
Assembly pluginAssembly = LoadPlugin(pluginPath);
return CreateCommands(pluginAssembly,this);
}).ToList();
Console.WriteLine("AppWithPlugin is initialized.");
}

Expand Down Expand Up @@ -136,9 +163,19 @@ public void Main(string[] args)
return _sp.GetService<T>();
}

public bool AddService<T>(T service)
public bool AddService<T, T2>()
{
throw new NotImplementedException();
try
{
_sc = (_sc ?? new ServiceCollection()).AddSingleton(typeof(T), typeof(T2));
_sp = _sc!.BuildServiceProvider();
return true;
}
catch (Exception ex)
{
Console.WriteLine(ex);
return false;
}
}

public bool ShowMessage(string message)
Expand Down
47 changes: 43 additions & 4 deletions TestStatements/AppWithPlugin/Model/Logging.cs
Original file line number Diff line number Diff line change
@@ -1,24 +1,63 @@
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Diagnostics;

namespace AppWithPlugin.Model
{
public class Logging : ILogger
{
{
public static Action<string> _logAction { get; set; } = (s) => Debug.WriteLine(s);

List<IDisposable> _scopes = new();

private class Scope : IDisposable
{
private readonly Logging _logger;

public WeakReference<object> State => state;

WeakReference<object> state;
public Scope(Logging logger,object state)
{
_logger = logger;
this.state = new(state);
_logger._scopes.Add(this);
}
public void Dispose()
{
_logger._scopes.Remove(this);
}
}

public IDisposable? BeginScope<TState>(TState state) where TState : notnull
{
throw new NotImplementedException();
if (state is IDisposable disposable)
{
if (!_scopes.Contains(disposable))
{
_scopes.Add(disposable);
return disposable;
}
return null;
}
else
{
return new Scope(this, state);
}
}

public bool IsEnabled(LogLevel logLevel)
{
throw new NotImplementedException();
return true;
}

public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception? exception, Func<TState, Exception?, string> formatter)
{
Debug.WriteLine($"[{logLevel}] {eventId.Id} {formatter(state, exception)}");
if (IsEnabled(logLevel))
{
_logAction($"[{logLevel}] {eventId.Id} {formatter(state, exception)}");
}
}
}
}
23 changes: 22 additions & 1 deletion TestStatements/AppWithPlugin/Model/PluginLoadContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,27 +6,48 @@ namespace AppWithPlugin.Model;

class PluginLoadContext : AssemblyLoadContext
{
#if NET5_0_OR_GREATER
private AssemblyDependencyResolver _resolver;
#else
private string? assemblyPath;
#endif

public PluginLoadContext(string pluginPath)
{
#if NET5_0_OR_GREATER
_resolver = new AssemblyDependencyResolver(pluginPath);
#else
assemblyPath = pluginPath;
#endif
}

protected override Assembly? Load(AssemblyName assemblyName)
{
#if NET5_0_OR_GREATER
string? assemblyPath = _resolver.ResolveAssemblyToPath(assemblyName);
#else
string? assemblyPath = this.assemblyPath;
#endif

if (assemblyPath != null)
{
return LoadFromAssemblyPath(assemblyPath);

Assembly assembly = LoadFromAssemblyPath(assemblyPath);
if (!assembly?.IsFullyTrusted ?? false)
return null;
return assembly;
}

return null;
}

protected override nint LoadUnmanagedDll(string unmanagedDllName)
{
#if NET5_0_OR_GREATER
string? libraryPath = _resolver.ResolveUnmanagedDllToPath(unmanagedDllName);
#else
string? libraryPath = this.assemblyPath;
#endif
if (libraryPath != null)
{
return LoadUnmanagedDllFromPath(libraryPath);
Expand Down
34 changes: 34 additions & 0 deletions TestStatements/AppWithPluginTest/AppWithPluginTest.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<Project>
<ImportGroup Label="SolutionProps">
<Import Project="..\Solution_net.props" />
</ImportGroup>

<PropertyGroup>
<TargetFrameworks>net6.0;net7.0;net8.0;net9.0</TargetFrameworks>
<LangVersion>latest</LangVersion>
</PropertyGroup>
<Import Sdk="Microsoft.NET.Sdk" Project="Sdk.props" />
<Import Sdk="Microsoft.NET.Sdk" Project="Sdk.targets" />
<ItemGroup>
<Compile Include="..\..\CSharpBible\Libraries\BaseLib\Helper\ClassHelper.cs" Link="Helper\ClassHelper.cs" />
</ItemGroup>

<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.12.0" />
<PackageReference Include="MSTest" Version="3.7.0" />
<PackageReference Include="NSubstitute" Version="5.3.0" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\AppWithPlugin\AppWithPlugin.csproj" />
</ItemGroup>

<ItemGroup>
<Using Include="Microsoft.VisualStudio.TestTools.UnitTesting" />
</ItemGroup>

<ItemGroup>
<Folder Include="Helper\" />
</ItemGroup>

</Project>
86 changes: 86 additions & 0 deletions TestStatements/AppWithPluginTest/Model/AppWithPluginTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using AppWithPlugin.Model;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace AppWithPlugin.Model.Tests
{
[TestClass()]
public class AppWithPluginTests
{
private AppWithPlugin _testClass;

private interface ISomeService
{
string Test { get; set; }
}

private class SomeService : ISomeService
{
public string Test { get; set; }
}

[TestInitialize]
public void Initialize()
{
_testClass = new AppWithPlugin();
}

[TestMethod()]
public void SetUp()
{
Assert.IsNotNull(_testClass);
}

[TestMethod]
public void InitializeTest()
{
// Arrange
// Act
_testClass.Initialize([""]);
// Assert
Assert.IsTrue(true);
}

[TestMethod()]
public void MainTest()
{
// Arrange
string[] args = new string[] { "Test" };
// Act
_testClass.Main(args);
// Assert
Assert.IsTrue(true);
}

[TestMethod()]
public void GetServiceTest()
{
// Arrange
_testClass.AddService<ISomeService, SomeService>();

// Act
var result = _testClass.GetService<ISomeService>();

// Assert
Assert.IsNotNull(result);
Assert.IsInstanceOfType( result,typeof(SomeService));
Assert.IsInstanceOfType(result, typeof(ISomeService));
}

[TestMethod()]
public void AddServiceTest()
{
Assert.Fail();
}

[TestMethod()]
public void ShowMessageTest()
{
Assert.Fail();
}
}
}
Loading
Loading