diff --git a/Alpm/Alpm.csproj b/Alpm/Alpm.csproj
index 7d9d041..69449f0 100644
--- a/Alpm/Alpm.csproj
+++ b/Alpm/Alpm.csproj
@@ -7,4 +7,8 @@
Foodsoft.Alpm
+
+
+
+
diff --git a/Alpm/AlpmException.cs b/Alpm/AlpmException.cs
index 349e6b1..9d2305a 100644
--- a/Alpm/AlpmException.cs
+++ b/Alpm/AlpmException.cs
@@ -8,8 +8,8 @@ namespace Foodsoft.Alpm
{
public AlpmException() { }
internal AlpmException(SafeAlpmHandle handle) : base(alpm.alpm_strerror(alpm.alpm_errno(handle))) { }
- public AlpmException(Error errno) : base(alpm.alpm_strerror(errno)) { }
- public AlpmException(Error errno, Exception inner) : base(alpm.alpm_strerror(errno), inner) { }
+ public AlpmException(ErrorCode errno) : base(alpm.alpm_strerror(errno)) { }
+ public AlpmException(ErrorCode errno, Exception inner) : base(alpm.alpm_strerror(errno), inner) { }
protected AlpmException(SerializationInfo info,
StreamingContext context) : base(info, context) { }
diff --git a/Alpm/Backup.cs b/Alpm/Backup.cs
index 0fbf072..557f71f 100644
--- a/Alpm/Backup.cs
+++ b/Alpm/Backup.cs
@@ -6,7 +6,7 @@ namespace Foodsoft.Alpm
public readonly struct Backup : IEquatable
{
public string Name { get; }
- public string Hash { get; }
+ public string? Hash { get; }
public bool Equals(Backup other)
{
@@ -24,17 +24,17 @@ namespace Foodsoft.Alpm
}
[StructLayout(LayoutKind.Sequential)]
- private readonly unsafe struct NativeBackup
+ private readonly struct NativeBackup
{
- internal readonly sbyte* name;
- internal readonly sbyte* hash;
+ internal readonly IntPtr name;
+ internal readonly IntPtr hash;
}
internal unsafe Backup(IntPtr ptr)
{
var native = (NativeBackup*) ptr;
- Name = new string(native->name);
- Hash = new string(native->hash);
+ Name = Marshal.PtrToStringUTF8(native->name)!;
+ Hash = Marshal.PtrToStringUTF8(native->hash)!;
}
}
}
\ No newline at end of file
diff --git a/Alpm/CachePackage.cs b/Alpm/CachePackage.cs
index 47fbd29..749e5ee 100644
--- a/Alpm/CachePackage.cs
+++ b/Alpm/CachePackage.cs
@@ -15,7 +15,7 @@ namespace Foodsoft.Alpm
var ret = alpm.alpm_pkg_checkmd5sum(Handle);
if (ret == 0) return true;
var errno = alpm.alpm_errno(Handle.SafeAlpmHandle);
- return errno == Error.PkgInvalid ? false : throw new AlpmException(errno);
+ return errno == ErrorCode.PkgInvalid ? false : throw new AlpmException(errno);
}
public void SetInstallReason(InstallReason reason)
diff --git a/Alpm/Database.cs b/Alpm/Database.cs
index f2c590d..a85381f 100644
--- a/Alpm/Database.cs
+++ b/Alpm/Database.cs
@@ -42,7 +42,7 @@ namespace Foodsoft.Alpm
// ReSharper disable once LoopCanBeConvertedToQuery
foreach (var s in value)
if (alpm.alpm_list_append_strdup(ref listPtr, s) == IntPtr.Zero)
- throw new AlpmException(Error.Memory);
+ throw new AlpmException(ErrorCode.Memory);
success = true;
}
@@ -63,8 +63,8 @@ namespace Foodsoft.Alpm
public SigLevel SigLevel => alpm.alpm_db_get_siglevel(_handle);
- public Error Valid =>
- alpm.alpm_db_get_valid(_handle) != 0 ? alpm.alpm_errno(_handle.SafeAlpmHandle) : Error.OK;
+ public ErrorCode Valid =>
+ alpm.alpm_db_get_valid(_handle) != 0 ? alpm.alpm_errno(_handle.SafeAlpmHandle) : ErrorCode.OK;
public CachePackageList PackageCache
{
@@ -118,7 +118,7 @@ namespace Foodsoft.Alpm
if (pkgPtr == IntPtr.Zero)
{
var err = alpm.alpm_errno(_handle.SafeAlpmHandle);
- if (err == Error.PkgNotFound)
+ if (err == ErrorCode.PkgNotFound)
return null;
throw new AlpmException(err);
}
@@ -134,7 +134,7 @@ namespace Foodsoft.Alpm
if (result == IntPtr.Zero)
{
var errNo = alpm.alpm_errno(_handle.SafeAlpmHandle);
- if (errNo != Error.OK)
+ if (errNo != ErrorCode.OK)
throw new AlpmException(errNo);
}
diff --git a/Alpm/Depend.cs b/Alpm/Depend.cs
index 7edae39..d3ea9db 100644
--- a/Alpm/Depend.cs
+++ b/Alpm/Depend.cs
@@ -5,22 +5,12 @@ namespace Foodsoft.Alpm
{
public class Depend : IEquatable
{
- public enum ModType
- {
- Any = 1,
- Equal,
- GreaterThanOrEqual,
- LessThanOrEqual,
- GreaterThan,
- LessThan
- }
-
internal unsafe Depend(IntPtr ptr)
{
var native = (NativeDepend*) ptr;
- Name = new string(native->name);
- Version = new string(native->version);
- Description = new string(native->description);
+ Name = Marshal.PtrToStringUTF8(native->name)!;
+ Version = Marshal.PtrToStringUTF8(native->version)!;
+ Description = Marshal.PtrToStringUTF8(native->description)!;
NameHash = native->name_hash;
Mod = native->mod;
}
@@ -48,13 +38,23 @@ namespace Foodsoft.Alpm
}
[StructLayout(LayoutKind.Sequential)]
- private readonly unsafe struct NativeDepend
+ private readonly struct NativeDepend
{
- internal readonly sbyte* name;
- internal readonly sbyte* version;
- internal readonly sbyte* description;
+ internal readonly IntPtr name;
+ internal readonly IntPtr version;
+ internal readonly IntPtr description;
internal readonly ulong name_hash;
internal readonly ModType mod;
}
}
+
+ public enum ModType
+ {
+ Any = 1,
+ Equal,
+ GreaterThanOrEqual,
+ LessThanOrEqual,
+ GreaterThan,
+ LessThan
+ }
}
\ No newline at end of file
diff --git a/Alpm/Detail.cs b/Alpm/Detail.cs
index 25f9fee..a304322 100644
--- a/Alpm/Detail.cs
+++ b/Alpm/Detail.cs
@@ -80,7 +80,7 @@ namespace Foodsoft.Alpm
Encoding.UTF8.GetBytes(pSrc, s.Length, pDest, poolBuffer.Length - start);
pDest[nbWritten] = 0;
if (alpm.alpm_list_append(ref listPtr, (IntPtr) pDest) == IntPtr.Zero)
- throw new AlpmException(Error.Memory);
+ throw new AlpmException(ErrorCode.Memory);
start += nbWritten + 1;
}
diff --git a/Alpm/Enums.cs b/Alpm/ErrorCode.cs
similarity index 72%
rename from Alpm/Enums.cs
rename to Alpm/ErrorCode.cs
index c9fee62..464ebd6 100644
--- a/Alpm/Enums.cs
+++ b/Alpm/ErrorCode.cs
@@ -1,8 +1,6 @@
-using System;
-
namespace Foodsoft.Alpm
{
- public enum Error
+ public enum ErrorCode
{
OK = 0,
Memory,
@@ -80,28 +78,4 @@ namespace Foodsoft.Alpm
/*MissingCompileTimeFeatures*/
MissingCapabilitySignatures
}
-
- [Flags]
- public enum LogLevel
- {
- Error = 1,
- Warning = (1 << 1),
- Debug = (1 << 2),
- Function = (1 << 3)
- }
-
- [Flags]
- public enum SigLevel
- {
- Package = (1 << 0),
- PackageOptional = (1 << 1),
- PackageMarginalOK = (1 << 2),
- PackageUnknownOK = (1 << 3),
-
- Database = (1 << 10),
- DatabaseOptional = (1 << 11),
- DatabaseMarginalOK = (1 << 12),
- DatabaseUnknownOK = (1 << 13),
- UseDefault = (1 << 31)
- }
}
\ No newline at end of file
diff --git a/Alpm/ExtensionMethods.cs b/Alpm/ExtensionMethods.cs
index aad94f3..b9d147f 100644
--- a/Alpm/ExtensionMethods.cs
+++ b/Alpm/ExtensionMethods.cs
@@ -28,7 +28,7 @@ namespace Foodsoft.Alpm
refs[pkgPtr] = pkg;
if (alpm.alpm_list_append(ref listPtr, handle.DangerousGetHandle()) == IntPtr.Zero)
- throw new AlpmException(Error.Memory);
+ throw new AlpmException(ErrorCode.Memory);
}
var foundPtr = alpm.alpm_find_satisfier(listPtr, depString);
diff --git a/Alpm/Handle.cs b/Alpm/Handle.cs
index fb0fe1f..51ac99c 100644
--- a/Alpm/Handle.cs
+++ b/Alpm/Handle.cs
@@ -1,15 +1,19 @@
using System;
using System.Collections.Generic;
+using Foodsoft.Alpm.Interop;
namespace Foodsoft.Alpm
{
public sealed class Handle : IDisposable
{
+ private readonly object _eventLock = new object();
private readonly SafeAlpmHandle _handle;
- public Handle(string root, string dbpath)
+ private EventHandler _logEvent;
+
+ public Handle(string root, string dbPath)
{
- _handle = alpm.alpm_initialize(root, dbpath, out var err);
+ _handle = alpm.alpm_initialize(root, dbPath, out var err);
if (_handle.IsInvalid) throw new AlpmException(err);
}
@@ -22,6 +26,8 @@ namespace Foodsoft.Alpm
set => Detail.SetStringCollection(value, _handle, s => alpm.alpm_option_add_cachedir(_handle, s));
}
+ public LogLevel LogLevel { get; set; }
+
public void Dispose()
{
_handle.Dispose();
@@ -55,5 +61,42 @@ namespace Foodsoft.Alpm
{
return alpm.alpm_pkg_should_ignore(_handle, pkg.Handle) == 0;
}
+
+ public event EventHandler Log
+ {
+ add
+ {
+ void LogCallback(LogLevel level, IntPtr format, IntPtr args)
+ {
+ if (level > LogLevel) return;
+ _logEvent?.Invoke(this,
+ new LogEventArgs {Level = level, Message = CFormatter.Format(format, args)});
+ }
+
+ lock (_eventLock)
+ {
+ var wasEmpty = _logEvent == null;
+ _logEvent += value;
+ if (wasEmpty)
+ alpm.alpm_option_set_logcb(_handle, LogCallback);
+ }
+ }
+ remove
+ {
+ lock (_eventLock)
+ {
+ // ReSharper disable once DelegateSubtraction
+ _logEvent -= value;
+ if (_logEvent == null)
+ alpm.alpm_option_set_logcb(_handle, null);
+ }
+ }
+ }
+
+ public struct LogEventArgs
+ {
+ public LogLevel Level;
+ public string Message;
+ }
}
}
\ No newline at end of file
diff --git a/Alpm/Interop/CFormatter.cs b/Alpm/Interop/CFormatter.cs
new file mode 100644
index 0000000..873da2f
--- /dev/null
+++ b/Alpm/Interop/CFormatter.cs
@@ -0,0 +1,88 @@
+using System;
+using System.Buffers;
+using System.Runtime.InteropServices;
+using System.Text;
+
+namespace Foodsoft.Alpm.Interop
+{
+ internal static class CFormatter
+ {
+ private static readonly int vaListCopyNWords;
+
+ private static readonly Vsnprintf? vsnprintfFunc;
+
+ static CFormatter()
+ {
+ if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux) ||
+ RuntimeInformation.IsOSPlatform(OSPlatform.FreeBSD))
+ {
+ vaListCopyNWords = RuntimeInformation.ProcessArchitecture switch
+ {
+ Architecture.X86 => 1,
+ Architecture.X64 => 3,
+ Architecture.Arm => 1,
+ Architecture.Arm64 => 4,
+ _ => vaListCopyNWords
+ };
+ vsnprintfFunc = vsnprintfLibc;
+ }
+ else if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
+ {
+ vaListCopyNWords = 1;
+ vsnprintfFunc = vsnprintfUCrt;
+ }
+ else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
+ {
+ vaListCopyNWords = RuntimeInformation.ProcessArchitecture switch
+ {
+ Architecture.X86 => 1,
+ Architecture.X64 => 3,
+ Architecture.Arm => 1,
+ Architecture.Arm64 => 1,
+ _ => vaListCopyNWords
+ };
+ vsnprintfFunc = vsnprintfLibc;
+ }
+ }
+
+ internal static unsafe string Format(IntPtr format, IntPtr vaList)
+ {
+ const int bufSize = 256;
+ if (vsnprintfFunc == null || vaListCopyNWords <= 0)
+ return "[Formatter unsupported for platform]";
+
+ var vaListBuf = (void**) vaList;
+ var vaListCopy = stackalloc void*[vaListCopyNWords];
+ for (var i = 0; i < vaListCopyNWords; i++) vaListCopy[i] = vaListBuf[i];
+
+ var strBuf = stackalloc byte[bufSize];
+ var strBufPtr = (IntPtr) strBuf;
+
+ var nbNeed = vsnprintfFunc(strBufPtr, (UIntPtr) bufSize, format, vaList);
+
+ if (nbNeed < bufSize)
+ return Marshal.PtrToStringUTF8(strBufPtr, nbNeed);
+
+ var pool = ArrayPool.Shared;
+
+ var buffer = pool.Rent(nbNeed + 1);
+ fixed (byte* pb = buffer)
+ {
+ nbNeed = vsnprintfFunc((IntPtr) pb, (UIntPtr) buffer.Length, format, (IntPtr) vaListCopy);
+ }
+
+ var result = Encoding.UTF8.GetString(buffer, 0, nbNeed);
+ pool.Return(buffer);
+ return result;
+ }
+
+ private delegate int Vsnprintf(IntPtr buffer, UIntPtr size, IntPtr format, IntPtr args);
+
+
+ [DllImport("libc", EntryPoint = "vsnprintf", CallingConvention = CallingConvention.Cdecl)]
+ internal static extern int vsnprintfLibc(IntPtr buffer, UIntPtr size, IntPtr format, IntPtr args);
+
+ [DllImport("ucrt", EntryPoint = "vsnprintf", CallingConvention = CallingConvention.Cdecl)]
+ internal static extern int vsnprintfUCrt(IntPtr buffer, UIntPtr size, IntPtr format, IntPtr args);
+ }
+}
\ No newline at end of file
diff --git a/Alpm/Marshalling/UTF8In.cs b/Alpm/Interop/UTF8In.cs
similarity index 89%
rename from Alpm/Marshalling/UTF8In.cs
rename to Alpm/Interop/UTF8In.cs
index 0ab686a..3d8059d 100644
--- a/Alpm/Marshalling/UTF8In.cs
+++ b/Alpm/Interop/UTF8In.cs
@@ -1,5 +1,7 @@
using System;
+using System.Diagnostics.CodeAnalysis;
using System.Runtime.InteropServices;
+using JetBrains.Annotations;
namespace Foodsoft.Alpm.Marshalling
{
@@ -30,9 +32,8 @@ namespace Foodsoft.Alpm.Marshalling
{
return Marshal.PtrToStringUTF8(pNativeData)!;
}
-
- // ReSharper disable once UnusedMember.Local
- // ReSharper disable once UnusedParameter.Local
+
+ [UsedImplicitly]
private static ICustomMarshaler GetInstance(string cookie)
{
return _instance;
diff --git a/Alpm/Marshalling/UTF8Return.cs b/Alpm/Interop/UTF8Return.cs
similarity index 88%
rename from Alpm/Marshalling/UTF8Return.cs
rename to Alpm/Interop/UTF8Return.cs
index 39ffb81..fb578f1 100644
--- a/Alpm/Marshalling/UTF8Return.cs
+++ b/Alpm/Interop/UTF8Return.cs
@@ -1,5 +1,6 @@
using System;
using System.Runtime.InteropServices;
+using JetBrains.Annotations;
namespace Foodsoft.Alpm.Marshalling
{
@@ -7,8 +8,7 @@ namespace Foodsoft.Alpm.Marshalling
{
private static readonly UTF8Return _instance = default;
- // ReSharper disable once UnusedMember.Local
- // ReSharper disable once UnusedParameter.Local
+ [UsedImplicitly]
private static ICustomMarshaler GetInstance(string cookie)
{
return _instance;
diff --git a/Alpm/LogLevel.cs b/Alpm/LogLevel.cs
new file mode 100644
index 0000000..9c344f4
--- /dev/null
+++ b/Alpm/LogLevel.cs
@@ -0,0 +1,13 @@
+using System;
+
+namespace Foodsoft.Alpm
+{
+ [Flags]
+ public enum LogLevel
+ {
+ Error = 1,
+ Warning = (1 << 1),
+ Debug = (1 << 2),
+ Function = (1 << 3)
+ }
+}
\ No newline at end of file
diff --git a/Alpm/Package.cs b/Alpm/Package.cs
index 83bc8e8..a100f3a 100644
--- a/Alpm/Package.cs
+++ b/Alpm/Package.cs
@@ -5,10 +5,7 @@ namespace Foodsoft.Alpm
{
public abstract class Package : IPackageData
{
- internal Package(SafePackageHandle handle)
- {
- Handle = handle;
- }
+ internal Package(SafePackageHandle handle) => Handle = handle;
internal SafePackageHandle Handle { get; }
@@ -57,24 +54,15 @@ namespace Foodsoft.Alpm
public virtual Database? DB => null;
- public void Dispose()
- {
- Handle.Dispose();
- }
+ public void Dispose() => Handle.Dispose();
- public IEnumerable ComputeRequiredBy()
- {
- throw new NotImplementedException();
- }
+ public IEnumerable ComputeRequiredBy() => throw new NotImplementedException();
public IEnumerable ComputeOptionalFor()
{
throw new NotImplementedException();
}
- public static int VersionCompare(string v1, string v2)
- {
- return alpm.alpm_pkg_vercmp(v1, v2);
- }
+ public static int VersionCompare(string v1, string v2) => alpm.alpm_pkg_vercmp(v1, v2);
}
}
\ No newline at end of file
diff --git a/Alpm/SafeFilePackageHandle.cs b/Alpm/SafeFilePackageHandle.cs
index c1229de..8646ea4 100644
--- a/Alpm/SafeFilePackageHandle.cs
+++ b/Alpm/SafeFilePackageHandle.cs
@@ -4,7 +4,7 @@ using System.Runtime.ConstrainedExecution;
namespace Foodsoft.Alpm
{
- internal class SafeFilePackageHandle : SafePackageHandle
+ internal sealed class SafeFilePackageHandle : SafePackageHandle
{
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
[PrePrepareMethod]
diff --git a/Alpm/SigLevel.cs b/Alpm/SigLevel.cs
new file mode 100644
index 0000000..1649a7e
--- /dev/null
+++ b/Alpm/SigLevel.cs
@@ -0,0 +1,19 @@
+using System;
+
+namespace Foodsoft.Alpm
+{
+ [Flags]
+ public enum SigLevel
+ {
+ Package = (1 << 0),
+ PackageOptional = (1 << 1),
+ PackageMarginalOK = (1 << 2),
+ PackageUnknownOK = (1 << 3),
+
+ Database = (1 << 10),
+ DatabaseOptional = (1 << 11),
+ DatabaseMarginalOK = (1 << 12),
+ DatabaseUnknownOK = (1 << 13),
+ UseDefault = (1 << 31)
+ }
+}
\ No newline at end of file
diff --git a/Alpm/alpm.cs b/Alpm/alpm.cs
index a744f1d..ace1ef4 100644
--- a/Alpm/alpm.cs
+++ b/Alpm/alpm.cs
@@ -16,7 +16,6 @@ namespace Foodsoft.Alpm
// ReSharper disable once InconsistentNaming
internal static class alpm
{
- // ReSharper disable once InconsistentNaming
public delegate void alpm_fn_free(IntPtr ptr);
[DllImport(nameof(alpm))]
@@ -145,6 +144,12 @@ namespace Foodsoft.Alpm
[DllImport(nameof(alpm))]
public static extern int alpm_pkg_free(IntPtr ptr);
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+ internal delegate void LogFuncCallBack(LogLevel level, IntPtr format, IntPtr argsAddress);
+
+ [DllImport(nameof(alpm))]
+ public static extern IntPtr alpm_option_set_logcb(SafeAlpmHandle handle, LogFuncCallBack? cb);
+
[DllImport(nameof(alpm))]
public static extern IntPtr alpm_option_get_cachedirs(SafeAlpmHandle handle);
@@ -159,11 +164,11 @@ namespace Foodsoft.Alpm
string cachedir);
[DllImport(nameof(alpm))]
- public static extern Error alpm_errno(SafeAlpmHandle handle);
+ public static extern ErrorCode alpm_errno(SafeAlpmHandle handle);
[DllImport(nameof(alpm))]
[return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8Return))]
- public static extern string alpm_strerror(Error err);
+ public static extern string alpm_strerror(ErrorCode err);
[DllImport(nameof(alpm))]
public static extern IntPtr alpm_get_localdb(SafeAlpmHandle handle);
@@ -218,7 +223,7 @@ namespace Foodsoft.Alpm
public static extern SafeAlpmHandle alpm_initialize(
[MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8In))]
string root, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8In))]
- string dbpath, out Error err);
+ string dbpath, out ErrorCode err);
[DllImport(nameof(alpm))]
public static extern int alpm_release(IntPtr handle);
diff --git a/DotNetAlpm.sln.DotSettings b/DotNetAlpm.sln.DotSettings
index 2431c01..09bed35 100644
--- a/DotNetAlpm.sln.DotSettings
+++ b/DotNetAlpm.sln.DotSettings
@@ -2,11 +2,16 @@
True
True
True
+ True
True
+ True
True
True
True
True
True
True
- True
\ No newline at end of file
+ True
+ True
+ True
+ True
\ No newline at end of file
diff --git a/Samples/Program.cs b/Samples/Program.cs
index 0eea377..855a38c 100644
--- a/Samples/Program.cs
+++ b/Samples/Program.cs
@@ -1,27 +1,24 @@
using System;
-using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using System.Reflection;
-using System.Runtime.CompilerServices;
using Foodsoft.Alpm;
-// ReSharper disable once UnusedType.Global
namespace Samples
{
[Example("installed")]
internal class Installed : IExample
{
- private static string ModToStr(Depend.ModType modType)
+ private static string ModToStr(ModType modType)
{
return modType switch
{
- Depend.ModType.Any => "",
- Depend.ModType.Equal => "==",
- Depend.ModType.GreaterThanOrEqual => ">=",
- Depend.ModType.LessThanOrEqual => "<=",
- Depend.ModType.GreaterThan => ">",
- Depend.ModType.LessThan => "<",
+ ModType.Any => "",
+ ModType.Equal => "==",
+ ModType.GreaterThanOrEqual => ">=",
+ ModType.LessThanOrEqual => "<=",
+ ModType.GreaterThan => ">",
+ ModType.LessThan => "<",
_ => throw new ArgumentOutOfRangeException(nameof(modType), modType, null)
};
}
@@ -60,7 +57,7 @@ namespace Samples
//using var pkg = db.PackageCache.FindSatisfier("gcc=9.3.0-1");
- var result = db.Search(new string[] {"gcc", "objc"});
+ var result = db.Search(new[] {"gcc", "objc"});
foreach (var pkg in result)
using (pkg)
{
@@ -82,7 +79,7 @@ namespace Samples
var examples = (from t in Assembly.GetExecutingAssembly().GetTypes()
let attribute = (Example?) t.GetCustomAttribute(typeof(Example))
where attribute != null
- select new {Name = attribute.Name, Type = t}).ToImmutableDictionary((e) => e.Name);
+ select new {attribute.Name, Type = t}).ToImmutableDictionary((e) => e.Name);
if (args.Length < 1)
{
@@ -110,7 +107,7 @@ namespace Samples
}
}
- [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct, AllowMultiple = false)]
+ [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct)]
public class Example : Attribute
{
public string Name { get; }