背景:
为了去除多余的代码,我使用了策略模式。因此,我将这个(前一个(冗余代码放入策略模式的上下文类中,其中将调用方法IsSuccess ProcessApiMethod((。上下文类不是我的问题所在,我只是为了完整性向您展示它。
难度:
如果TOut是一个类,- 方法ProcessApiMethod((应返回null
- 但是TOut也可以是像int或bool这样的基本类型
到目前为止已解决:
- 此外,某些API方法将具有返回类型void。这就是我实现两个不同接口的原因
我的问题-困难在于:
- C#是否允许替代通用约束
- 如何允许基本类型作为T的可能类型
我错过了以下内容。。。
public interface ISuccessConverterStrategy<TOut> where Tout : (class || basicType)
但这毫无意义:
public interface ISuccessConverterStrategy<TOut> where Tout : (class || (!class && !struct))
- 如果"否";是你对我第一个问题的回答:我该如何解决这个问题
目前,无论我如何尝试,在我的策略类中,编译器告诉我">接口成员"TOut SuccessConverter.ISuccessConverterStrategie.GetResult(("未实现"或者他提到了使用这些泛型的另一个问题。
这是我完整的代码:
public enum IsSuccess
{
No = - 1,
NotSupported = 0,
Yes = 1,
WithoutContent = 2
}
/// <sumary>
/// Interface of Strategy Pattern
/// </summary>
public interface ISuccessConverterStrategy
{
IsSuccess ProcessApiMethod();
}
public interface ISuccessConverterStrategy<TOut> : ISuccessConverterStrategy
{
/// <summary>
/// After processing
/// Returns null, if processing method has no return value.
/// Returns null, if something went wrong.
/// Returns return value, otherwise.
/// </summary>
/// <typeparam name="TOut"></typeparam>
/// <returns></returns>
TOut GetResult<TOut>();
}
/// <summary>
/// Context class of strategy pattern.
/// </summary>
public class SilentSuccessConverter
{
/// <summary>
/// Silences API-method when called within strategy-method. Extends range of possible return values
/// of type IsSuccess, e.g. by IsSuccess.NotSupported. Catches possible exception messages.
/// </summary>
/// <param name="strategy"></param>
/// <param name="errorMessage"></param>
/// <returns></returns>
/// <exception cref="NullReferenceException"></exception>
public IsSuccess Convert(ISuccessConverterStrategy strategy, out string errorMessage)
{
if (null == strategy)
{
throw new NullReferenceException(nameof(strategy));
}
errorMessage = "";
try
{
return strategy.ProcessApiMethod();
}
catch (Exception e) when (e.Message.ToLower().Contains("not implemented"))
{
errorMessage = $" - Message: {e.Message} - Source: {e.Source}" + Environment.NewLine;
return IsSuccess.NotSupported;
}
catch (Exception e)
{
errorMessage = $" - Message: {e.Message} - Source: {e.Source}" + Environment.NewLine;
if (e is NotImplementedException || e is NotSupportedException)
{
return IsSuccess.NotSupported;
}
return IsSuccess.No;
}
}
}
public class FuncTOutClassStrategy<TOut> : ISuccessConverterStrategy<TOut> where TOut : class
{
private Func<TOut> _apiMethod;
private TOut _result;
/// <summary>
/// Holds a method without parameters, which returns an generic class object.
/// </summary>
/// <param name="apiMethod"></param>
public void SetApiMethod(Func<TOut> apiMethod)
{
_apiMethod = apiMethod ?? throw new NullReferenceException(nameof(apiMethod));
}
public IsSuccess ProcessApiMethod()
{
_result = _apiMethod();
return null != _result ? IsSuccess.Yes : IsSuccess.No;
}
public TOut GetResult()
{
return _result;
}
}
public class FuncIntOutStrategy<int> : ISuccessConverterStrategy<int>
{
private Func<int> _apiMethod;
private int _result;
/// <summary>
/// Holds a method without parameters, which returns int.
/// </summary>
/// <param name="apiMethod"></param>
public void SetApiMethod(Func<int> apiMethod)
{
_apiMethod = apiMethod ?? throw new NullReferenceException(nameof(apiMethod));
}
public IsSuccess ProcessApiMethod()
{
_result = _apiMethod();
return _result > 0 ? IsSuccess.Yes : IsSuccess.No;
}
public int GetResult()
{
return _result;
}
}
public class ActionTInStrategy<TIn> : ISuccessConverterStrategy
{
private Action<TIn> _apiMethod;
private TIn _input;
/// <summary>
/// Holds a void method that receives an object of type T.
/// </summary>
/// <param name="apiMethod"></param>
/// <param name="input"></param>
public void SetApiMethod(Action<TIn> apiMethod, TIn input)
{
_input = input;
_apiMethod = apiMethod ?? throw new NullReferenceException(nameof(apiMethod));
}
public IsSuccess ProcessApiMethod()
{
_apiMethod(_input);
return IsSuccess.Yes;
}
}
public class ActionStrategy : ISuccessConverterStrategy
{
private Action _apiMethod;
/// <summary>
/// Holds a void method without any parameters.
/// </summary>
/// <param name="apiMethod"></param>
public void SetApiMethod(Action apiMethod)
{
_apiMethod = apiMethod ?? throw new NullReferenceException(nameof(apiMethod));
}
public IsSuccess ProcessApiMethod()
{
_apiMethod();
return IsSuccess.Yes;
}
}
现在我想我得到它没有错误。这些是我修改的代码部分:
public interface ISuccessConverterStrategy<out TOut> : ISuccessConverterStrategy
{
/// <summary>
/// After processing
/// Returns null, if processing method has no return value.
/// Returns null, if something went wrong.
/// Returns return value, otherwise.
/// </summary>
/// <typeparam name="TOut"></typeparam>
/// <returns></returns>
TOut GetResult();
}
public class FuncBoolOutStrategy : ISuccessConverterStrategy<bool>
{
private Func<bool> _apiMethod;
private bool _result;
/// <summary>
/// Holds a method without parameters, which returns bool.
/// </summary>
/// <param name="apiMethod"></param>
public void SetApiMethod(Func<bool> apiMethod)
{
_apiMethod = apiMethod ?? throw new NullReferenceException(nameof(apiMethod));
}
public IsSuccess ProcessApiMethod()
{
_result = _apiMethod();
return _result ? IsSuccess.Yes : IsSuccess.No;
}
public bool GetResult()
{
return _result;
}
}
public class FuncIntOutStrategy : ISuccessConverterStrategy<int>
{
private Func<int> _apiMethod;
private int _result;
/// <summary>
/// Holds a method without parameters, which returns int.
/// </summary>
/// <param name="apiMethod"></param>
public void SetApiMethod(Func<int> apiMethod)
{
_apiMethod = apiMethod ?? throw new NullReferenceException(nameof(apiMethod));
}
public IsSuccess ProcessApiMethod()
{
_result = _apiMethod();
return _result > 0 ? IsSuccess.Yes : IsSuccess.No;
}
public int GetResult()
{
return _result;
}
}
public class FuncTOutClassStrategy<TOut> : ISuccessConverterStrategy<TOut> where TOut : class
{
private Func<TOut> _apiMethod;
private TOut _result;
/// <summary>
/// Holds a method without parameters, which returns an generic class object.
/// </summary>
/// <param name="apiMethod"></param>
public void SetApiMethod(Func<TOut> apiMethod)
{
_apiMethod = apiMethod ?? throw new NullReferenceException(nameof(apiMethod));
}
public IsSuccess ProcessApiMethod()
{
_result = _apiMethod();
return null != _result ? IsSuccess.Yes : IsSuccess.No;
}
public TOut GetResult()
{
return _result;
}
}
也许你发现了一些需要改进的地方,比如必要的约束或。