带接口的工厂模式,如何避免转换
Factory pattern with interface, how to avoid cast
我尝试使用接口实现工厂模式以创建不同类型的响应,但我不知道我做的是否正确。当我用工厂 class 调用我的方法 SetExceptionResponse
时,我必须强制转换它。
接口:
public interface IResponse
{
int ErrorCode { get; set; }
HeaderResponse HeaderResponse { get; set; }
IResponse SetExceptionResponse(int code, string title, string[] errors);
}
主要 class :
public class Response : IResponse
{
public int ErrorCode { get ; set ; }
public HeaderResponse HeaderResponse { get; set; } = null;
public virtual IResponse SetExceptionResponse(int code, string title, string[] errors)
{
HeaderResponse headerResponse = new HeaderResponse();
if (errors.Length > 0)
{
foreach (string item in errors)
headerResponse.ErrorList.Add(item);
}
headerResponse.Title = title;
headerResponse.StatusCode = code;
return new Response
{
ErrorCode = code,
HeaderResponse = headerResponse
};
}
}
继承主class的其他class:
public class DeleteShipmentResponse : Response
{
public string Value { get; set; }
public override string ToString()
{
return JsonConvert.SerializeObject(this);
}
public override IResponse SetExceptionResponse(int code, string title, string[] errors)
{
HeaderResponse headerResponse = new HeaderResponse();
if (errors.Length > 0)
{
foreach (string item in errors)
headerResponse.ErrorList.Add(item);
}
headerResponse.Title = title;
headerResponse.StatusCode = code;
return new DeleteShipmentResponse
{
ErrorCode = code,
HeaderResponse = headerResponse
};
}
我的工厂class:
public static class ResponseFactory
{
public static IResponse CreateResponse()
{
return new Response();
}
public static IResponse CreateDeleteResponse()
{
return new DeleteShipmentResponse();
}
public static IResponse CreateShipmentResponse()
{
return new ShipmentResponse();
}
public static T CreateResponse<T>()
where T : IResponse
{
return (T)CreateResponse(typeof(T));
}
public static IResponse CreateResponse(Type type)
{
if (type == typeof(Response))
return CreateResponse();
if (type == typeof(DeleteShipmentResponse))
return CreateDeleteResponse();
else if (type == typeof(ShipmentResponse))
return CreateShipmentResponse();
else
throw new ArgumentOutOfRangeException(string.Format(CultureInfo.InvariantCulture, "Unrecognized type [{0}]", type.FullName), "type");
}
}
因此,当我使用工厂创建 DeleteShipmentResponse 并调用 SetExeceptionResponse 时,我这样做了:
DeleteShipmentResponse result = (DeleteShipmentResponse)ResponseFactory.CreateResponse<DeleteShipmentResponse>().SetExceptionResponse(500, "Exception in DeleteShipment()", new string[] { ex.Message });
我必须使用 DeleteShipmentResponse 进行转换,否则会抛出异常。
如何在不强制转换为 DeleteShipmentResponse 的情况下获得它?
我必须使用通用接口吗?
感谢帮助
如果所有 IResponse
都可以有一个无参数的构造函数,您可以使 IResponse
泛型“自身”,即 T
约束为 IResponse<T>
:
public interface IResponse<T> where T : IResponse<T>
{
int ErrorCode { get; set; }
HeaderResponse HeaderResponse { get; set; }
T SetExceptionResponse(int code, string title, string[] errors);
}
public class Response<T> : IResponse<T> where T : IResponse<T>, new
{
public int ErrorCode { get; set; }
public HeaderResponse HeaderResponse { get; set; } = null;
public virtual T SetExceptionResponse(int code, string title, string[] errors)
{
HeaderResponse headerResponse = new HeaderResponse();
.....
return new T
{
ErrorCode = code,
HeaderResponse = headerResponse
};
}
}
public class DeleteShipmentResponse : Response<DeleteShipmentResponse>
{
...
public override DeleteShipmentResponse SetExceptionResponse(int code, string title, string[] errors)
{
....
return new DeleteShipmentResponse
{
ErrorCode = code,
HeaderResponse = headerResponse
};
}
}
我尝试使用接口实现工厂模式以创建不同类型的响应,但我不知道我做的是否正确。当我用工厂 class 调用我的方法 SetExceptionResponse
时,我必须强制转换它。
接口:
public interface IResponse
{
int ErrorCode { get; set; }
HeaderResponse HeaderResponse { get; set; }
IResponse SetExceptionResponse(int code, string title, string[] errors);
}
主要 class :
public class Response : IResponse
{
public int ErrorCode { get ; set ; }
public HeaderResponse HeaderResponse { get; set; } = null;
public virtual IResponse SetExceptionResponse(int code, string title, string[] errors)
{
HeaderResponse headerResponse = new HeaderResponse();
if (errors.Length > 0)
{
foreach (string item in errors)
headerResponse.ErrorList.Add(item);
}
headerResponse.Title = title;
headerResponse.StatusCode = code;
return new Response
{
ErrorCode = code,
HeaderResponse = headerResponse
};
}
}
继承主class的其他class:
public class DeleteShipmentResponse : Response
{
public string Value { get; set; }
public override string ToString()
{
return JsonConvert.SerializeObject(this);
}
public override IResponse SetExceptionResponse(int code, string title, string[] errors)
{
HeaderResponse headerResponse = new HeaderResponse();
if (errors.Length > 0)
{
foreach (string item in errors)
headerResponse.ErrorList.Add(item);
}
headerResponse.Title = title;
headerResponse.StatusCode = code;
return new DeleteShipmentResponse
{
ErrorCode = code,
HeaderResponse = headerResponse
};
}
我的工厂class:
public static class ResponseFactory
{
public static IResponse CreateResponse()
{
return new Response();
}
public static IResponse CreateDeleteResponse()
{
return new DeleteShipmentResponse();
}
public static IResponse CreateShipmentResponse()
{
return new ShipmentResponse();
}
public static T CreateResponse<T>()
where T : IResponse
{
return (T)CreateResponse(typeof(T));
}
public static IResponse CreateResponse(Type type)
{
if (type == typeof(Response))
return CreateResponse();
if (type == typeof(DeleteShipmentResponse))
return CreateDeleteResponse();
else if (type == typeof(ShipmentResponse))
return CreateShipmentResponse();
else
throw new ArgumentOutOfRangeException(string.Format(CultureInfo.InvariantCulture, "Unrecognized type [{0}]", type.FullName), "type");
}
}
因此,当我使用工厂创建 DeleteShipmentResponse 并调用 SetExeceptionResponse 时,我这样做了:
DeleteShipmentResponse result = (DeleteShipmentResponse)ResponseFactory.CreateResponse<DeleteShipmentResponse>().SetExceptionResponse(500, "Exception in DeleteShipment()", new string[] { ex.Message });
我必须使用 DeleteShipmentResponse 进行转换,否则会抛出异常。
如何在不强制转换为 DeleteShipmentResponse 的情况下获得它? 我必须使用通用接口吗?
感谢帮助
如果所有 IResponse
都可以有一个无参数的构造函数,您可以使 IResponse
泛型“自身”,即 T
约束为 IResponse<T>
:
public interface IResponse<T> where T : IResponse<T>
{
int ErrorCode { get; set; }
HeaderResponse HeaderResponse { get; set; }
T SetExceptionResponse(int code, string title, string[] errors);
}
public class Response<T> : IResponse<T> where T : IResponse<T>, new
{
public int ErrorCode { get; set; }
public HeaderResponse HeaderResponse { get; set; } = null;
public virtual T SetExceptionResponse(int code, string title, string[] errors)
{
HeaderResponse headerResponse = new HeaderResponse();
.....
return new T
{
ErrorCode = code,
HeaderResponse = headerResponse
};
}
}
public class DeleteShipmentResponse : Response<DeleteShipmentResponse>
{
...
public override DeleteShipmentResponse SetExceptionResponse(int code, string title, string[] errors)
{
....
return new DeleteShipmentResponse
{
ErrorCode = code,
HeaderResponse = headerResponse
};
}
}