Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
N
netcoreplus
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
tsai
netcoreplus
Commits
4355e858
Commit
4355e858
authored
May 17, 2019
by
阿星Plus
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
MemoryCache
parent
1abcfbfe
Changes
6
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
534 additions
and
6 deletions
+534
-6
Plus.csproj
src/Plus/Plus.csproj
+2
-0
CacheBase.cs
src/Plus/Runtime/Caching/CacheBase.cs
+340
-0
CacheExtensions.cs
src/Plus/Runtime/Caching/CacheExtensions.cs
+6
-6
CacheManagerBase.cs
src/Plus/Runtime/Caching/CacheManagerBase.cs
+76
-0
MemoryCacheManager.cs
src/Plus/Runtime/Caching/Memory/MemoryCacheManager.cs
+39
-0
PlusMemoryCache.cs
src/Plus/Runtime/Caching/Memory/PlusMemoryCache.cs
+71
-0
No files found.
src/Plus/Plus.csproj
View file @
4355e858
...
...
@@ -7,6 +7,8 @@
<ItemGroup>
<PackageReference Include="Castle.Core" Version="4.4.0" />
<PackageReference Include="Castle.Windsor" Version="5.0.0" />
<PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="2.2.0" />
<PackageReference Include="Nito.AsyncEx.Coordination" Version="5.0.0" />
<PackageReference Include="System.Collections.Immutable" Version="1.5.0" />
<PackageReference Include="System.ComponentModel.Annotations" Version="4.5.0" />
</ItemGroup>
...
...
src/Plus/Runtime/Caching/CacheBase.cs
0 → 100644
View file @
4355e858
using
Castle.Core.Logging
;
using
Nito.AsyncEx
;
using
System
;
using
System.Collections.Generic
;
using
System.Linq
;
using
System.Threading.Tasks
;
namespace
Plus.Runtime.Caching
{
/// <summary>
/// Base class for caches.
/// It's used to simplify implementing <see cref="ICache"/>.
/// </summary>
public
abstract
class
CacheBase
:
ICache
{
public
ILogger
Logger
{
get
;
set
;
}
public
string
Name
{
get
;
}
public
TimeSpan
DefaultSlidingExpireTime
{
get
;
set
;
}
public
TimeSpan
?
DefaultAbsoluteExpireTime
{
get
;
set
;
}
protected
readonly
object
SyncObj
=
new
object
();
private
readonly
AsyncLock
_asyncLock
=
new
AsyncLock
();
/// <summary>
/// Constructor.
/// </summary>
/// <param name="name"></param>
protected
CacheBase
(
string
name
)
{
Name
=
name
;
DefaultSlidingExpireTime
=
TimeSpan
.
FromHours
(
1
);
Logger
=
NullLogger
.
Instance
;
}
public
virtual
object
Get
(
string
key
,
Func
<
string
,
object
>
factory
)
{
object
item
=
null
;
try
{
item
=
GetOrDefault
(
key
);
}
catch
(
Exception
ex
)
{
Logger
.
Error
(
ex
.
ToString
(),
ex
);
}
if
(
item
==
null
)
{
lock
(
SyncObj
)
{
try
{
item
=
GetOrDefault
(
key
);
}
catch
(
Exception
ex
)
{
Logger
.
Error
(
ex
.
ToString
(),
ex
);
}
if
(
item
==
null
)
{
item
=
factory
(
key
);
if
(
item
==
null
)
{
return
null
;
}
try
{
Set
(
key
,
item
);
}
catch
(
Exception
ex
)
{
Logger
.
Error
(
ex
.
ToString
(),
ex
);
}
}
}
}
return
item
;
}
public
virtual
object
[]
Get
(
string
[]
keys
,
Func
<
string
,
object
>
factory
)
{
object
[]
items
=
null
;
try
{
items
=
GetOrDefault
(
keys
);
}
catch
(
Exception
ex
)
{
Logger
.
Error
(
ex
.
ToString
(),
ex
);
}
if
(
items
==
null
)
{
items
=
new
object
[
keys
.
Length
];
}
if
(
items
.
Any
(
i
=>
i
==
null
))
{
lock
(
SyncObj
)
{
try
{
items
=
GetOrDefault
(
keys
);
}
catch
(
Exception
ex
)
{
Logger
.
Error
(
ex
.
ToString
(),
ex
);
}
var
fetched
=
new
List
<
KeyValuePair
<
string
,
object
>>();
for
(
var
i
=
0
;
i
<
items
.
Length
;
i
++)
{
string
key
=
keys
[
i
];
object
value
=
items
[
i
];
if
(
value
==
null
)
{
value
=
factory
(
key
);
}
if
(
value
!=
null
)
{
fetched
.
Add
(
new
KeyValuePair
<
string
,
object
>(
key
,
value
));
}
}
if
(
fetched
.
Any
())
{
try
{
Set
(
fetched
.
ToArray
());
}
catch
(
Exception
ex
)
{
Logger
.
Error
(
ex
.
ToString
(),
ex
);
}
}
}
}
return
items
;
}
public
virtual
async
Task
<
object
>
GetAsync
(
string
key
,
Func
<
string
,
Task
<
object
>>
factory
)
{
object
item
=
null
;
try
{
item
=
await
GetOrDefaultAsync
(
key
);
}
catch
(
Exception
ex
)
{
Logger
.
Error
(
ex
.
ToString
(),
ex
);
}
if
(
item
==
null
)
{
using
(
await
_asyncLock
.
LockAsync
())
{
try
{
item
=
await
GetOrDefaultAsync
(
key
);
}
catch
(
Exception
ex
)
{
Logger
.
Error
(
ex
.
ToString
(),
ex
);
}
if
(
item
==
null
)
{
item
=
await
factory
(
key
);
if
(
item
==
null
)
{
return
null
;
}
try
{
await
SetAsync
(
key
,
item
);
}
catch
(
Exception
ex
)
{
Logger
.
Error
(
ex
.
ToString
(),
ex
);
}
}
}
}
return
item
;
}
public
virtual
async
Task
<
object
[
]>
GetAsync
(
string
[]
keys
,
Func
<
string
,
Task
<
object
>>
factory
)
{
object
[]
items
=
null
;
try
{
items
=
await
GetOrDefaultAsync
(
keys
);
}
catch
(
Exception
ex
)
{
Logger
.
Error
(
ex
.
ToString
(),
ex
);
}
if
(
items
==
null
)
{
items
=
new
object
[
keys
.
Length
];
}
if
(
items
.
Any
(
i
=>
i
==
null
))
{
using
(
await
_asyncLock
.
LockAsync
())
{
try
{
items
=
await
GetOrDefaultAsync
(
keys
);
}
catch
(
Exception
ex
)
{
Logger
.
Error
(
ex
.
ToString
(),
ex
);
}
var
fetched
=
new
List
<
KeyValuePair
<
string
,
object
>>();
for
(
var
i
=
0
;
i
<
items
.
Length
;
i
++)
{
string
key
=
keys
[
i
];
object
value
=
items
[
i
];
if
(
value
==
null
)
{
value
=
factory
(
key
);
}
if
(
value
!=
null
)
{
fetched
.
Add
(
new
KeyValuePair
<
string
,
object
>(
key
,
value
));
}
}
if
(
fetched
.
Any
())
{
try
{
await
SetAsync
(
fetched
.
ToArray
());
}
catch
(
Exception
ex
)
{
Logger
.
Error
(
ex
.
ToString
(),
ex
);
}
}
}
}
return
items
;
}
public
abstract
object
GetOrDefault
(
string
key
);
public
virtual
object
[]
GetOrDefault
(
string
[]
keys
)
{
return
keys
.
Select
(
GetOrDefault
).
ToArray
();
}
public
virtual
Task
<
object
>
GetOrDefaultAsync
(
string
key
)
{
return
Task
.
FromResult
(
GetOrDefault
(
key
));
}
public
virtual
Task
<
object
[
]>
GetOrDefaultAsync
(
string
[]
keys
)
{
return
Task
.
FromResult
(
GetOrDefault
(
keys
));
}
public
abstract
void
Set
(
string
key
,
object
value
,
TimeSpan
?
slidingExpireTime
=
null
,
TimeSpan
?
absoluteExpireTime
=
null
);
public
virtual
void
Set
(
KeyValuePair
<
string
,
object
>[]
pairs
,
TimeSpan
?
slidingExpireTime
=
null
,
TimeSpan
?
absoluteExpireTime
=
null
)
{
foreach
(
var
pair
in
pairs
)
{
Set
(
pair
.
Key
,
pair
.
Value
,
slidingExpireTime
,
absoluteExpireTime
);
}
}
public
virtual
Task
SetAsync
(
string
key
,
object
value
,
TimeSpan
?
slidingExpireTime
=
null
,
TimeSpan
?
absoluteExpireTime
=
null
)
{
Set
(
key
,
value
,
slidingExpireTime
,
absoluteExpireTime
);
return
Task
.
FromResult
(
0
);
}
public
virtual
Task
SetAsync
(
KeyValuePair
<
string
,
object
>[]
pairs
,
TimeSpan
?
slidingExpireTime
=
null
,
TimeSpan
?
absoluteExpireTime
=
null
)
{
return
Task
.
WhenAll
(
pairs
.
Select
(
p
=>
SetAsync
(
p
.
Key
,
p
.
Value
,
slidingExpireTime
,
absoluteExpireTime
)));
}
public
abstract
void
Remove
(
string
key
);
public
virtual
void
Remove
(
string
[]
keys
)
{
foreach
(
var
key
in
keys
)
{
Remove
(
key
);
}
}
public
virtual
Task
RemoveAsync
(
string
key
)
{
Remove
(
key
);
return
Task
.
FromResult
(
0
);
}
public
virtual
Task
RemoveAsync
(
string
[]
keys
)
{
return
Task
.
WhenAll
(
keys
.
Select
(
RemoveAsync
));
}
public
abstract
void
Clear
();
public
virtual
Task
ClearAsync
()
{
Clear
();
return
Task
.
FromResult
(
0
);
}
public
virtual
void
Dispose
()
{
}
}
}
\ No newline at end of file
src/Plus/Runtime/Caching/CacheExtensions.cs
View file @
4355e858
...
...
@@ -60,7 +60,7 @@ namespace Plus.Runtime.Caching
var
value
=
await
cache
.
GetAsync
(
key
.
ToString
(),
async
(
keyAsString
)
=>
{
var
v
=
await
factory
(
key
);
return
(
object
)
v
;
return
v
;
});
return
(
TValue
)
value
;
...
...
@@ -73,7 +73,7 @@ namespace Plus.Runtime.Caching
return
cache
.
GetAsync
(
key
.
ToString
(),
async
(
keyAsString
)
=>
{
var
v
=
await
factory
(
key
);
return
(
object
)
v
;
return
v
;
});
});
var
values
=
await
Task
.
WhenAll
(
tasks
);
...
...
@@ -96,7 +96,7 @@ namespace Plus.Runtime.Caching
var
value
=
cache
.
GetOrDefault
(
key
.
ToString
());
if
(
value
==
null
)
{
return
default
(
TValue
)
;
return
default
;
}
return
(
TValue
)
value
;
...
...
@@ -109,7 +109,7 @@ namespace Plus.Runtime.Caching
var
value
=
cache
.
GetOrDefault
(
key
.
ToString
());
if
(
value
==
null
)
{
return
default
(
TValue
)
;
return
default
;
}
return
(
TValue
)
value
;
});
...
...
@@ -122,7 +122,7 @@ namespace Plus.Runtime.Caching
var
value
=
await
cache
.
GetOrDefaultAsync
(
key
.
ToString
());
if
(
value
==
null
)
{
return
default
(
TValue
)
;
return
default
;
}
return
(
TValue
)
value
;
...
...
@@ -135,7 +135,7 @@ namespace Plus.Runtime.Caching
var
value
=
await
cache
.
GetOrDefaultAsync
(
key
.
ToString
());
if
(
value
==
null
)
{
return
default
(
TValue
)
;
return
default
;
}
return
(
TValue
)
value
;
});
...
...
src/Plus/Runtime/Caching/CacheManagerBase.cs
0 → 100644
View file @
4355e858
using
Plus.Dependency
;
using
Plus.Runtime.Caching.Configuration
;
using
System.Collections.Concurrent
;
using
System.Collections.Generic
;
using
System.Collections.Immutable
;
using
System.Linq
;
namespace
Plus.Runtime.Caching
{
/// <summary>
/// Base class for cache managers.
/// </summary>
public
abstract
class
CacheManagerBase
:
ICacheManager
,
ISingletonDependency
{
protected
readonly
IIocManager
IocManager
;
protected
readonly
ICachingConfiguration
Configuration
;
protected
readonly
ConcurrentDictionary
<
string
,
ICache
>
Caches
;
/// <summary>
/// Constructor.
/// </summary>
/// <param name="iocManager"></param>
/// <param name="configuration"></param>
protected
CacheManagerBase
(
IIocManager
iocManager
,
ICachingConfiguration
configuration
)
{
IocManager
=
iocManager
;
Configuration
=
configuration
;
Caches
=
new
ConcurrentDictionary
<
string
,
ICache
>();
}
public
IReadOnlyList
<
ICache
>
GetAllCaches
()
{
return
Caches
.
Values
.
ToImmutableList
();
}
public
virtual
ICache
GetCache
(
string
name
)
{
return
Caches
.
GetOrAdd
(
name
,
(
cacheName
)
=>
{
var
cache
=
CreateCacheImplementation
(
cacheName
);
var
configurators
=
Configuration
.
Configurators
.
Where
(
c
=>
c
.
CacheName
==
null
||
c
.
CacheName
==
cacheName
);
foreach
(
var
configurator
in
configurators
)
{
configurator
.
InitAction
?.
Invoke
(
cache
);
}
return
cache
;
});
}
public
virtual
void
Dispose
()
{
DisposeCaches
();
Caches
.
Clear
();
}
protected
virtual
void
DisposeCaches
()
{
foreach
(
var
cache
in
Caches
)
{
IocManager
.
Release
(
cache
.
Value
);
}
}
/// <summary>
/// Used to create actual cache implementation.
/// </summary>
/// <param name="name">Name of the cache</param>
/// <returns>Cache object</returns>
protected
abstract
ICache
CreateCacheImplementation
(
string
name
);
}
}
\ No newline at end of file
src/Plus/Runtime/Caching/Memory/MemoryCacheManager.cs
0 → 100644
View file @
4355e858
using
Castle.Core.Logging
;
using
Plus.Dependency
;
using
Plus.Runtime.Caching.Configuration
;
namespace
Plus.Runtime.Caching.Memory
{
/// <summary>
/// Implements <see cref="ICacheManager"/> to work with MemoryCache.
/// </summary>
public
class
AbpMemoryCacheManager
:
CacheManagerBase
{
public
ILogger
Logger
{
get
;
set
;
}
/// <summary>
/// Constructor.
/// </summary>
public
AbpMemoryCacheManager
(
IIocManager
iocManager
,
ICachingConfiguration
configuration
)
:
base
(
iocManager
,
configuration
)
{
Logger
=
NullLogger
.
Instance
;
}
protected
override
ICache
CreateCacheImplementation
(
string
name
)
{
return
new
AbpMemoryCache
(
name
)
{
Logger
=
Logger
};
}
protected
override
void
DisposeCaches
()
{
foreach
(
var
cache
in
Caches
.
Values
)
{
cache
.
Dispose
();
}
}
}
}
\ No newline at end of file
src/Plus/Runtime/Caching/Memory/PlusMemoryCache.cs
0 → 100644
View file @
4355e858
using
Microsoft.Extensions.Caching.Memory
;
using
Microsoft.Extensions.Options
;
using
System
;
namespace
Plus.Runtime.Caching.Memory
{
/// <summary>
/// Implements <see cref="ICache"/> to work with <see cref="MemoryCache"/>.
/// </summary>
public
class
AbpMemoryCache
:
CacheBase
{
private
MemoryCache
_memoryCache
;
/// <summary>
/// Constructor.
/// </summary>
/// <param name="name">Unique name of the cache</param>
public
AbpMemoryCache
(
string
name
)
:
base
(
name
)
{
_memoryCache
=
new
MemoryCache
(
new
OptionsWrapper
<
MemoryCacheOptions
>(
new
MemoryCacheOptions
()));
}
public
override
object
GetOrDefault
(
string
key
)
{
return
_memoryCache
.
Get
(
key
);
}
public
override
void
Set
(
string
key
,
object
value
,
TimeSpan
?
slidingExpireTime
=
null
,
TimeSpan
?
absoluteExpireTime
=
null
)
{
if
(
value
==
null
)
{
throw
new
PlusException
(
"Can not insert null values to the cache!"
);
}
if
(
absoluteExpireTime
!=
null
)
{
_memoryCache
.
Set
(
key
,
value
,
DateTimeOffset
.
Now
.
Add
(
absoluteExpireTime
.
Value
));
}
else
if
(
slidingExpireTime
!=
null
)
{
_memoryCache
.
Set
(
key
,
value
,
slidingExpireTime
.
Value
);
}
else
if
(
DefaultAbsoluteExpireTime
!=
null
)
{
_memoryCache
.
Set
(
key
,
value
,
DateTimeOffset
.
Now
.
Add
(
DefaultAbsoluteExpireTime
.
Value
));
}
else
{
_memoryCache
.
Set
(
key
,
value
,
DefaultSlidingExpireTime
);
}
}
public
override
void
Remove
(
string
key
)
{
_memoryCache
.
Remove
(
key
);
}
public
override
void
Clear
()
{
_memoryCache
.
Dispose
();
_memoryCache
=
new
MemoryCache
(
new
OptionsWrapper
<
MemoryCacheOptions
>(
new
MemoryCacheOptions
()));
}
public
override
void
Dispose
()
{
_memoryCache
.
Dispose
();
base
.
Dispose
();
}
}
}
\ No newline at end of file
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment