ASP.NET
- 1 ответ
- 0 вопросов
0
Вклад в тег
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
//EXTERNAL CODE
//Приведен только для справки, никак нельзя менять, код обфусцирован, исходников нет
public sealed class ExternalDataProvider : IDisposable
{
public extern int LongRunningCalculation(int value, int value2);
public extern void Dispose();
}
/// <summary>
/// Объект-значение
/// <para>Базовый класс</para>
/// </summary>
public abstract class ValueObject<T> where T : ValueObject<T>
{
public static bool operator ==(ValueObject<T> value1, ValueObject<T> value2)
{
if ((object)value1 == null)
return (object)value2 == null;
return value1.Equals(value2);
}
public static bool operator !=(ValueObject<T> value1, ValueObject<T> value2)
{
return !(value1 == value2);
}
public override bool Equals(object obj)
{
var valueObject = obj as T;
if (ReferenceEquals(valueObject, null))
return false;
return CompareValues(valueObject);
}
public override int GetHashCode()
{
return GetValueHashCode();
}
/// <summary>
/// Получить HashCode
/// </summary>
/// <returns></returns>
protected abstract int GetValueHashCode();
/// <summary>
/// Сравнить значения
/// </summary>
/// <returns></returns>
protected abstract bool CompareValues(T other);
}
/// <summary>
/// Параметр для DataProvider
/// </summary>
public class Parameter : ValueObject<Parameter>
{
private Parameter()
{
FirstValue = -1;
SecondValue = -1;
}
public Parameter(int firstValue, int secondValue)
{
if (firstValue > 100 || firstValue < 0 || secondValue < 1 || secondValue > 12)
throw new ArgumentException("Is not supported values");
FirstValue = firstValue;
SecondValue = secondValue;
}
/// <summary>
/// Первый параметр
/// </summary>
public int FirstValue { get; }
/// <summary>
/// Второй параметр
/// </summary>
public int SecondValue { get; }
/// <summary>
/// Default value
/// </summary>
public static readonly Parameter Empty = new Parameter();
protected override bool CompareValues(Parameter other)
{
return FirstValue == other.FirstValue && SecondValue == other.SecondValue;
}
protected override int GetValueHashCode()
{
return (FirstValue, SecondValue).GetHashCode();
}
}
/// <summary>
/// Результат для DataProvider
/// </summary>
public class Result : ValueObject<Result>
{
private Result()
{
// Default value
Value = default;
}
public Result(int value)
{
Value = value;
}
/// <summary>
/// Результат
/// </summary>
public int Value { get; }
/// <summary>
/// Default value
/// </summary>
public static readonly Result Empty = new Result();
protected override bool CompareValues(Result other)
{
return Value == other.Value;
}
protected override int GetValueHashCode()
{
return Value.GetHashCode();
}
}
/// <summary>
/// Интерфейс DataProvider
/// </summary>
public interface IDataProvider
{
public Result GetResult(Parameter parameter);
}
/// <summary>
/// Получить данные из ExternalDataProvider без кеша
/// </summary>
public class DataProvider : IDataProvider
{
public Result GetResult(Parameter parameter)
{
using var externalDataProvider = new ExternalDataProvider();
return new Result (externalDataProvider.LongRunningCalculation(parameter.FirstValue, parameter.SecondValue));
}
}
/// <summary>
/// DataProvider с кешированием данных
/// Реализация кеша не имеет принципиального значения
/// </summary>
public class CacheDataProvider : IDataProvider
{
private readonly IDataProvider dataProvider;
private readonly ConcurrentDictionary<Parameter, Result> cache = new();
public CacheDataProvider(IDataProvider dataProvider)
{
this.dataProvider = dataProvider;
}
public Result GetResult(Parameter parameter)
{
return cache.GetOrAdd(parameter, (p => dataProvider.GetResult(p)));
}
}