Browse Source

refactor models and remove cache run mode

v4/state-cache-providers
Quin Lynch 3 years ago
parent
commit
59c334ac60
14 changed files with 201 additions and 211 deletions
  1. +0
    -2
      src/Discord.Net.Core/Cache/ICached.cs
  2. +1
    -1
      src/Discord.Net.Core/Cache/Models/Users/IMemberModel.cs
  3. +0
    -1
      src/Discord.Net.Core/Cache/Models/Users/IThreadMemberModel.cs
  4. +2
    -2
      src/Discord.Net.Rest/API/Common/GuildMember.cs
  5. +0
    -1
      src/Discord.Net.Rest/API/Common/ThreadMember.cs
  6. +0
    -21
      src/Discord.Net.WebSocket/Cache/CacheRunMode.cs
  7. +57
    -19
      src/Discord.Net.WebSocket/Cache/DefaultConcurrentCacheProvider.cs
  8. +14
    -6
      src/Discord.Net.WebSocket/Cache/ICacheProvider.cs
  9. +33
    -37
      src/Discord.Net.WebSocket/ClientStateManager.Experiment.cs
  10. +26
    -31
      src/Discord.Net.WebSocket/Entities/Users/SocketGuildUser.cs
  11. +32
    -38
      src/Discord.Net.WebSocket/Entities/Users/SocketPresence.cs
  12. +14
    -20
      src/Discord.Net.WebSocket/Entities/Users/SocketSelfUser.cs
  13. +14
    -15
      src/Discord.Net.WebSocket/Entities/Users/SocketThreadUser.cs
  14. +8
    -17
      src/Discord.Net.WebSocket/Entities/Users/SocketUser.cs

+ 0
- 2
src/Discord.Net.Core/Cache/ICached.cs View File

@@ -11,8 +11,6 @@ namespace Discord
void Update(TType model);

TType ToModel();

TResult ToModel<TResult>() where TResult : TType, new();
}

public interface ICached


+ 1
- 1
src/Discord.Net.Core/Cache/Models/Users/IMemberModel.cs View File

@@ -12,7 +12,7 @@ namespace Discord
string Nickname { get; set; }
string GuildAvatar { get; set; }
ulong[] Roles { get; set; }
DateTimeOffset JoinedAt { get; set; }
DateTimeOffset? JoinedAt { get; set; }
DateTimeOffset? PremiumSince { get; set; }
bool IsDeaf { get; set; }
bool IsMute { get; set; }


+ 0
- 1
src/Discord.Net.Core/Cache/Models/Users/IThreadMemberModel.cs View File

@@ -9,7 +9,6 @@ namespace Discord
public interface IThreadMemberModel : IEntityModel<ulong>
{
ulong? ThreadId { get; set; }
ulong? UserId { get; set; }
DateTimeOffset JoinedAt { get; set; }
}
}

+ 2
- 2
src/Discord.Net.Rest/API/Common/GuildMember.cs View File

@@ -39,8 +39,8 @@ namespace Discord.API
get => Roles.GetValueOrDefault(Array.Empty<ulong>()); set => throw new NotSupportedException();
}

DateTimeOffset IMemberModel.JoinedAt {
get => JoinedAt.GetValueOrDefault(); set => throw new NotSupportedException();
DateTimeOffset? IMemberModel.JoinedAt {
get => JoinedAt.ToNullable(); set => throw new NotSupportedException();
}

DateTimeOffset? IMemberModel.PremiumSince {


+ 0
- 1
src/Discord.Net.Rest/API/Common/ThreadMember.cs View File

@@ -15,7 +15,6 @@ namespace Discord.API
public DateTimeOffset JoinTimestamp { get; set; }

ulong? IThreadMemberModel.ThreadId { get => ThreadId.ToNullable(); set => throw new NotSupportedException(); }
ulong? IThreadMemberModel.UserId { get => UserId.ToNullable(); set => throw new NotSupportedException(); }
DateTimeOffset IThreadMemberModel.JoinedAt { get => JoinTimestamp; set => throw new NotSupportedException(); }
ulong IEntityModel<ulong>.Id { get => UserId.GetValueOrDefault(0); set => throw new NotSupportedException(); }
}


+ 0
- 21
src/Discord.Net.WebSocket/Cache/CacheRunMode.cs View File

@@ -1,21 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Discord.WebSocket
{
public enum CacheRunMode
{
/// <summary>
/// The cache should preform a synchronous cache lookup.
/// </summary>
Sync,

/// <summary>
/// The cache should preform either a <see cref="Sync"/> or asynchronous cache lookup.
/// </summary>
Async
}
}

+ 57
- 19
src/Discord.Net.WebSocket/Cache/DefaultConcurrentCacheProvider.cs View File

@@ -12,6 +12,16 @@ namespace Discord.WebSocket
private readonly ConcurrentDictionary<Type, object> _storeCache = new();
private readonly ConcurrentDictionary<object, object> _subStoreCache = new();

private readonly Dictionary<Type, Type> _models = new()
{
{ typeof(IUserModel), typeof(API.User) },
{ typeof(ICurrentUserModel), typeof(API.CurrentUser) },
{ typeof(IMemberModel), typeof(API.GuildMember) },
{ typeof(IThreadMemberModel), typeof(API.ThreadMember)},
{ typeof(IPresenceModel), typeof(API.Presence)},
{ typeof(IActivityModel), typeof(API.Game)}
};

private class DefaultEntityStore<TModel, TId> : IEntityStore<TModel, TId>
where TModel : IEntityModel<TId>
where TId : IEquatable<TId>
@@ -23,44 +33,72 @@ namespace Discord.WebSocket
_cache = cache;
}

public ValueTask AddOrUpdateAsync(TModel model, CacheRunMode runmode)
public TModel Get(TId id)
{
_cache.AddOrUpdate(model.Id, model, (_, __) => model);
if (_cache.TryGetValue(id, out var model))
return model;
return default;
}

public ValueTask AddOrUpdateBatchAsync(IEnumerable<TModel> models, CacheRunMode runmode)
public IEnumerable<TModel> GetAll()
{
return _cache.Select(x => x.Value);
}
public void AddOrUpdate(TModel model)
{
_cache.AddOrUpdate(model.Id, model, (_, __) => model);
}
public void AddOrUpdateBatch(IEnumerable<TModel> models)
{
foreach (var model in models)
_cache.AddOrUpdate(model.Id, model, (_, __) => model);
return default;
}
public void Remove(TId id)
{
_cache.TryRemove(id, out _);
}
public void PurgeAll()
{
_cache.Clear();
}

public IAsyncEnumerable<TModel> GetAllAsync(CacheRunMode runmode)
ValueTask<TModel> IEntityStore<TModel, TId>.GetAsync(TId id) => new ValueTask<TModel>(Get(id));
IAsyncEnumerable<TModel> IEntityStore<TModel, TId>.GetAllAsync()
{
var coll = _cache.Select(x => x.Value).GetEnumerator();
return AsyncEnumerable.Create((_) => AsyncEnumerator.Create(
() => new ValueTask<bool>(coll.MoveNext()),
() => coll.Current,
() => new ValueTask()));
var enumerator = GetAll().GetEnumerator();
return AsyncEnumerable.Create((cancellationToken)
=> AsyncEnumerator.Create(
() => new ValueTask<bool>(enumerator.MoveNext()),
() => enumerator.Current,
() => new ValueTask())
);
}
public ValueTask<TModel> GetAsync(TId id, CacheRunMode runmode)
ValueTask IEntityStore<TModel, TId>.AddOrUpdateAsync(TModel model)
{
if (_cache.TryGetValue(id, out var model))
return new ValueTask<TModel>(model);
AddOrUpdate(model);
return default;
}
public ValueTask RemoveAsync(TId id, CacheRunMode runmode)
ValueTask IEntityStore<TModel, TId>.AddOrUpdateBatchAsync(IEnumerable<TModel> models)
{
_cache.TryRemove(id, out _);
AddOrUpdateBatch(models);
return default;
}

public ValueTask PurgeAllAsync(CacheRunMode runmode)
ValueTask IEntityStore<TModel, TId>.RemoveAsync(TId id)
{
_cache.Clear();
Remove(id);
return default;
}
ValueTask IEntityStore<TModel, TId>.PurgeAllAsync()
{
PurgeAll();
return default;
}
}

public Type GetModel<TInterface>()
{
if (_models.TryGetValue(typeof(TInterface), out var t))
return t;
return null;
}

public virtual ValueTask<IEntityStore<TModel, TId>> GetStoreAsync<TModel, TId>()


+ 14
- 6
src/Discord.Net.WebSocket/Cache/ICacheProvider.cs View File

@@ -8,6 +8,8 @@ namespace Discord.WebSocket
{
public interface ICacheProvider
{
Type GetModel<TModelInterface>();

ValueTask<IEntityStore<TModel, TId>> GetStoreAsync<TModel, TId>()
where TModel : IEntityModel<TId>
where TId : IEquatable<TId>;
@@ -21,11 +23,17 @@ namespace Discord.WebSocket
where TModel : IEntityModel<TId>
where TId : IEquatable<TId>
{
ValueTask<TModel> GetAsync(TId id, CacheRunMode runmode);
IAsyncEnumerable<TModel> GetAllAsync(CacheRunMode runmode);
ValueTask AddOrUpdateAsync(TModel model, CacheRunMode runmode);
ValueTask AddOrUpdateBatchAsync(IEnumerable<TModel> models, CacheRunMode runmode);
ValueTask RemoveAsync(TId id, CacheRunMode runmode);
ValueTask PurgeAllAsync(CacheRunMode runmode);
ValueTask<TModel> GetAsync(TId id);
TModel Get(TId id);
IAsyncEnumerable<TModel> GetAllAsync();
IEnumerable<TModel> GetAll();
ValueTask AddOrUpdateAsync(TModel model);
void AddOrUpdate(TModel model);
ValueTask AddOrUpdateBatchAsync(IEnumerable<TModel> models);
void AddOrUpdateBatch(IEnumerable<TModel> models);
ValueTask RemoveAsync(TId id);
void Remove(TId id);
ValueTask PurgeAllAsync();
void PurgeAll();
}
}

+ 33
- 37
src/Discord.Net.WebSocket/ClientStateManager.Experiment.cs View File

@@ -92,28 +92,6 @@ namespace Discord.WebSocket
}
}

private TResult RunOrThrowValueTask<TResult>(ValueTask<TResult> t)
{
if (_allowSyncWaits)
{
return t.GetAwaiter().GetResult();
}
else if (t.IsCompleted)
return t.Result;
else
throw new InvalidOperationException("Cannot run asynchronous value task in synchronous context");
}

private void RunOrThrowValueTask(ValueTask t)
{
if (_allowSyncWaits)
{
t.GetAwaiter().GetResult();
}
else if (!t.IsCompleted)
throw new InvalidOperationException("Cannot run asynchronous value task in synchronous context");
}

public async ValueTask InitializeAsync()
{
_store ??= await _cacheProvider.GetStoreAsync<TModel, TId>().ConfigureAwait(false);
@@ -137,7 +115,7 @@ namespace Discord.WebSocket
return entity;
}

var model = RunOrThrowValueTask(_store.GetAsync(id, CacheRunMode.Sync));
var model = _store.Get(id);

if (model != null)
{
@@ -156,7 +134,7 @@ namespace Discord.WebSocket
return entity;
}

var model = await _store.GetAsync(id, CacheRunMode.Async).ConfigureAwait(false);
var model = await _store.GetAsync(id).ConfigureAwait(false);

if (model != null)
{
@@ -175,7 +153,7 @@ namespace Discord.WebSocket

public IEnumerable<TEntity> GetAll()
{
var models = RunOrThrowValueTask(_store.GetAllAsync(CacheRunMode.Sync).ToArrayAsync());
var models = _store.GetAll();
return models.Select(x =>
{
var entity = _entityBuilder(x);
@@ -186,7 +164,7 @@ namespace Discord.WebSocket

public async IAsyncEnumerable<TEntity> GetAllAsync()
{
await foreach(var model in _store.GetAllAsync(CacheRunMode.Async))
await foreach(var model in _store.GetAllAsync())
{
var entity = _entityBuilder(model);
_references.TryAdd(model.Id, new CacheReference<TEntity>(entity));
@@ -212,13 +190,13 @@ namespace Discord.WebSocket
return (TEntity)entity;

var model = valueFactory(id);
await AddOrUpdateAsync(model);
await AddOrUpdateAsync(model).ConfigureAwait(false);
return _entityBuilder(model);
}

public void AddOrUpdate(TModel model)
{
RunOrThrowValueTask(_store.AddOrUpdateAsync(model, CacheRunMode.Sync));
_store.AddOrUpdate(model);
if (TryGetReference(model.Id, out var reference))
reference.Update(model);
}
@@ -227,14 +205,13 @@ namespace Discord.WebSocket
{
if (TryGetReference(model.Id, out var reference))
reference.Update(model);
return _store.AddOrUpdateAsync(model, CacheRunMode.Async);
return _store.AddOrUpdateAsync(model);
}

public void BulkAddOrUpdate(IEnumerable<TModel> models)
{
RunOrThrowValueTask(_store.AddOrUpdateBatchAsync(models, CacheRunMode.Sync));

foreach(var model in models)
_store.AddOrUpdateBatch(models);
foreach (var model in models)
{
if (_references.TryGetValue(model.Id, out var rf) && rf.Reference.TryGetTarget(out var entity))
entity.Update(model);
@@ -243,7 +220,7 @@ namespace Discord.WebSocket

public async ValueTask BulkAddOrUpdateAsync(IEnumerable<TModel> models)
{
await _store.AddOrUpdateBatchAsync(models, CacheRunMode.Async).ConfigureAwait(false);
await _store.AddOrUpdateBatchAsync(models).ConfigureAwait(false);

foreach (var model in models)
{
@@ -254,26 +231,26 @@ namespace Discord.WebSocket

public void Remove(TId id)
{
RunOrThrowValueTask(_store.RemoveAsync(id, CacheRunMode.Sync));
_store.Remove(id);
_references.TryRemove(id, out _);
}

public ValueTask RemoveAsync(TId id)
{
_references.TryRemove(id, out _);
return _store.RemoveAsync(id, CacheRunMode.Async);
return _store.RemoveAsync(id);
}

public void Purge()
{
RunOrThrowValueTask(_store.PurgeAllAsync(CacheRunMode.Sync));
_store.PurgeAll();
_references.Clear();
}

public ValueTask PurgeAsync()
{
_references.Clear();
return _store.PurgeAllAsync(CacheRunMode.Async);
return _store.PurgeAllAsync();
}

TEntity ILookupReferenceStore<TEntity, TId>.Get(TId id) => Get(id);
@@ -380,5 +357,24 @@ namespace Discord.WebSocket
_threadMemberLock.Release();
}
}

public ReferenceStore<SocketThreadUser, IThreadMemberModel, ulong, IThreadUser> GetThreadMemberStore(ulong threadId)
=> _threadMemberStores.TryGetValue(threadId, out var store) ? store : null;

public TModel GetModel<TModel, TFallback>()
where TFallback : class, TModel, new()
{
var type = _cacheProvider.GetModel<TModel>();

if (type != null)
{
if (!type.GetInterfaces().Contains(typeof(TModel)))
throw new InvalidOperationException($"Cannot use {type.Name} as a model for {typeof(TModel).Name}");

return (TModel)Activator.CreateInstance(type);
}
else
return new TFallback();
}
}
}

+ 26
- 31
src/Discord.Net.WebSocket/Entities/Users/SocketGuildUser.cs View File

@@ -74,7 +74,6 @@ namespace Discord.WebSocket
/// <inheritdoc />
public bool? IsPending { get; private set; }


/// <inheritdoc />
public DateTimeOffset? JoinedAt => DateTimeUtils.FromTicks(_joinedAtTicks);
/// <summary>
@@ -159,7 +158,7 @@ namespace Discord.WebSocket
}
internal void Update(MemberModel model)
{
_joinedAtTicks = model.JoinedAt.UtcTicks;
_joinedAtTicks = model.JoinedAt.HasValue ? model.JoinedAt.Value.UtcTicks : null;
Nickname = model.Nickname;
GuildAvatarId = model.GuildAvatar;
UpdateRoles(model.Roles);
@@ -232,6 +231,17 @@ namespace Discord.WebSocket

internal new SocketGuildUser Clone() => MemberwiseClone() as SocketGuildUser;

public override void Dispose()
{
if (IsFreed)
return;

GC.SuppressFinalize(this);
Discord.StateManager.GetMemberStore(_guildId)?.RemoveReference(Id);
IsFreed = true;
}
~SocketGuildUser() => Dispose();

#endregion

#region IGuildUser
@@ -249,7 +259,7 @@ namespace Discord.WebSocket

#region Cache

private struct CacheModel : MemberModel
private class CacheModel : MemberModel
{
public ulong Id { get; set; }
public string Nickname { get; set; }
@@ -258,7 +268,7 @@ namespace Discord.WebSocket

public ulong[] Roles { get; set; }

public DateTimeOffset JoinedAt { get; set; }
public DateTimeOffset? JoinedAt { get; set; }

public DateTimeOffset? PremiumSince { get; set; }

@@ -271,40 +281,25 @@ namespace Discord.WebSocket
public DateTimeOffset? CommunicationsDisabledUntil { get; set; }
}
internal new MemberModel ToModel()
=> ToModel<CacheModel>();

internal new TModel ToModel<TModel>() where TModel : MemberModel, new()
{
return new TModel
{
Id = Id,
CommunicationsDisabledUntil = TimedOutUntil,
GuildAvatar = GuildAvatarId,
IsDeaf = IsDeafened,
IsMute = IsMuted,
IsPending = IsPending,
JoinedAt = JoinedAt ?? DateTimeOffset.UtcNow, // review: nullable joined at here? should our model reflect this?
Nickname = Nickname,
PremiumSince = PremiumSince,
Roles = _roleIds.ToArray()
};
var model = Discord.StateManager.GetModel<MemberModel, CacheModel>();
model.Id = Id;
model.Nickname = Nickname;
model.GuildAvatar = GuildAvatarId;
model.Roles = _roleIds.ToArray();
model.JoinedAt = JoinedAt;
model.PremiumSince = PremiumSince;
model.IsDeaf = IsDeafened;
model.IsMute = IsMuted;
model.IsPending = IsPending;
model.CommunicationsDisabledUntil = TimedOutUntil;
return model;
}

MemberModel ICached<MemberModel>.ToModel()
=> ToModel();

TResult ICached<MemberModel>.ToModel<TResult>()
=> ToModel<TResult>();

void ICached<MemberModel>.Update(MemberModel model) => Update(model);

public override void Dispose()
{
GC.SuppressFinalize(this);
Discord.StateManager.GetMemberStore(_guildId)?.RemoveReference(Id);
}
~SocketGuildUser() => Dispose();

#endregion
}
}

+ 32
- 38
src/Discord.Net.WebSocket/Entities/Users/SocketPresence.cs View File

@@ -112,7 +112,6 @@ namespace Discord.WebSocket
internal SocketPresence Clone() => MemberwiseClone() as SocketPresence;

~SocketPresence() => Dispose();

public void Dispose()
{
if (IsFreed)
@@ -128,7 +127,7 @@ namespace Discord.WebSocket
}

#region Cache
private struct CacheModel : Model
private class CacheModel : Model
{
public UserStatus Status { get; set; }

@@ -187,48 +186,43 @@ namespace Discord.WebSocket
}

internal Model ToModel()
=> ToModel<CacheModel>();

internal TModel ToModel<TModel>() where TModel : Model, new()
{
return new TModel
var model = Discord.StateManager.GetModel<Model, CacheModel>();
model.Status = Status;
model.ActiveClients = ActiveClients.ToArray();
model.UserId = UserId;
model.GuildId = GuildId;
model.Activities = Activities.Select(x =>
{
Status = Status,
ActiveClients = ActiveClients.ToArray(),
UserId = UserId,
GuildId = GuildId,
Activities = Activities.Select(x =>
switch (x)
{
case Game game:
switch (game)
{
case RichGame richGame:
return richGame.ToModel<ActivityCacheModel>();
case SpotifyGame spotify:
return spotify.ToModel<ActivityCacheModel>();
case CustomStatusGame custom:
return custom.ToModel<ActivityCacheModel, EmojiCacheModel>();
case StreamingGame stream:
return stream.ToModel<ActivityCacheModel>();
}
break;
}

return new ActivityCacheModel
{
switch (x)
{
case Game game:
switch (game)
{
case RichGame richGame:
return richGame.ToModel<ActivityCacheModel>();
case SpotifyGame spotify:
return spotify.ToModel<ActivityCacheModel>();
case CustomStatusGame custom:
return custom.ToModel<ActivityCacheModel, EmojiCacheModel>();
case StreamingGame stream:
return stream.ToModel<ActivityCacheModel>();
}
break;
}

return new ActivityCacheModel
{
Name = x.Name,
Details = x.Details,
Flags = x.Flags,
Type = x.Type
};
}).ToArray(),
};
Name = x.Name,
Details = x.Details,
Flags = x.Flags,
Type = x.Type
};
}).ToArray();
return model;
}

Model ICached<Model>.ToModel() => ToModel();
TResult ICached<Model>.ToModel<TResult>() => ToModel<TResult>();
void ICached<Model>.Update(Model model) => Update(model);
bool ICached.IsFreed => IsFreed;



+ 14
- 20
src/Discord.Net.WebSocket/Entities/Users/SocketSelfUser.cs View File

@@ -97,7 +97,7 @@ namespace Discord.WebSocket
}

#region Cache
private struct CacheModel : Model
private class CacheModel : Model
{
public bool? IsVerified { get; set; }

@@ -125,29 +125,23 @@ namespace Discord.WebSocket
}

internal new Model ToModel()
=> ToModel<CacheModel>();

internal new TModel ToModel<TModel>() where TModel : Model, new()
{
return new TModel
{
Avatar = AvatarId,
Discriminator = Discriminator,
Email = Email,
Flags = Flags,
Id = Id,
IsBot = IsBot,
IsMfaEnabled = IsMfaEnabled,
IsVerified = IsVerified,
Locale = Locale,
PremiumType = this.PremiumType,
PublicFlags = PublicFlags ?? UserProperties.None,
Username = Username
};
var model = Discord.StateManager.GetModel<Model, CacheModel>();
model.Avatar = AvatarId;
model.Discriminator = Discriminator;
model.Email = Email;
model.Flags = Flags;
model.IsBot = IsBot;
model.IsMfaEnabled = IsMfaEnabled;
model.Locale = Locale;
model.PremiumType = PremiumType;
model.PublicFlags = PublicFlags ?? UserProperties.None;
model.Username = Username;
model.Id = Id;
return model;
}

Model ICached<Model>.ToModel() => ToModel();
TResult ICached<Model>.ToModel<TResult>() => ToModel<TResult>();
void ICached<Model>.Update(Model model) => Update(model);
#endregion
}


+ 14
- 15
src/Discord.Net.WebSocket/Entities/Users/SocketThreadUser.cs View File

@@ -151,14 +151,14 @@ namespace Discord.WebSocket

internal static SocketThreadUser Create(SocketGuild guild, SocketThreadChannel thread, Model model, SocketGuildUser member)
{
var entity = new SocketThreadUser(guild.Discord, guild.Id, thread.Id, model.UserId.Value);
var entity = new SocketThreadUser(guild.Discord, guild.Id, thread.Id, model.Id);
entity.Update(model);
return entity;
}

internal static SocketThreadUser Create(DiscordSocketClient client, ulong guildId, ulong threadId, Model model)
{
var entity = new SocketThreadUser(client, guildId, threadId, model.UserId.Value);
var entity = new SocketThreadUser(client, guildId, threadId, model.Id);
entity.Update(model);
return entity;
}
@@ -242,7 +242,12 @@ namespace Discord.WebSocket

public override void Dispose()
{
if (IsFreed)
return;

GC.SuppressFinalize(this);
Discord.StateManager.GetThreadMemberStore(_threadId)?.RemoveReference(Id);
IsFreed = true;
}


@@ -255,27 +260,21 @@ namespace Discord.WebSocket
#region Cache
private class CacheModel : Model
{
public ulong Id { get; set; }
public ulong? ThreadId { get; set; }
public ulong? UserId { get; set; }
public DateTimeOffset JoinedAt { get; set; }

ulong IEntityModel<ulong>.Id { get => UserId.GetValueOrDefault(); set => throw new NotSupportedException(); }
}

internal new Model ToModel() => ToModel<CacheModel>();

internal new TModel ToModel<TModel>() where TModel : Model, new()
internal new Model ToModel()
{
return new TModel
{
JoinedAt = ThreadJoinedAt,
ThreadId = _threadId,
UserId = Id
};
var model = Discord.StateManager.GetModel<Model, CacheModel>();
model.Id = Id;
model.ThreadId = _threadId;
model.JoinedAt = ThreadJoinedAt;
return model;
}

Model ICached<Model>.ToModel() => ToModel();
TResult ICached<Model>.ToModel<TResult>() => ToModel<TResult>();
void ICached<Model>.Update(Model model) => Update(model);
#endregion
}


+ 8
- 17
src/Discord.Net.WebSocket/Entities/Users/SocketUser.cs View File

@@ -137,29 +137,20 @@ namespace Discord.WebSocket
public ulong Id { get; set; }
}

internal TModel ToModel<TModel>() where TModel : Model, new()
internal Model ToModel()
{
return new TModel
{
Avatar = AvatarId,
Discriminator = Discriminator,
Id = Id,
IsBot = IsBot,
Username = Username
};
var model = Discord.StateManager.GetModel<Model, CacheModel>();
model.Avatar = AvatarId;
model.Discriminator = Discriminator;
model.Id = Id;
model.IsBot = IsBot;
model.Username = Username;
return model;
}

internal Model ToModel()
=> ToModel<CacheModel>();

Model ICached<Model>.ToModel()
=> ToModel();

TResult ICached<Model>.ToModel<TResult>()
=> ToModel<TResult>();

void ICached<Model>.Update(Model model) => Update(model);

bool ICached.IsFreed => IsFreed;

#endregion


Loading…
Cancel
Save