C# 工厂模式与界面,如何避免铸造

C# 工厂模式与界面,如何避免铸造,c#,generics,interface,factory,C#,Generics,Interface,Factory,我尝试用接口实现工厂模式来创建不同类型的响应,但我不知道我是否做对了。当我用工厂类调用我的方法SetExceptionResponse时,我必须强制转换它 接口: public interface IResponse { int ErrorCode { get; set; } HeaderResponse HeaderResponse { get; set; } IResponse SetExceptionResponse(int co

我尝试用接口实现工厂模式来创建不同类型的响应,但我不知道我是否做对了。当我用工厂类调用我的方法SetExceptionResponse时,我必须强制转换它

接口:

public interface IResponse
    {
        int ErrorCode { get; set; }

        HeaderResponse HeaderResponse { get; set; }

        IResponse SetExceptionResponse(int code, string title, string[] errors);
    }
主要类别:

    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
            };
        }
    }
其主要班级的其他班级:

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
            };
        }
我的工厂班级:

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");
        }
    }
因此,当我使用factory创建DeleteShipmentResponse并调用SetExeceptionResponse时,我会执行以下操作:

DeleteShipmentResponse result = (DeleteShipmentResponse)ResponseFactory.CreateResponse<DeleteShipmentResponse>().SetExceptionResponse(500, "Exception in DeleteShipment()", new string[] { ex.Message });
我必须使用DeleteShipmentResponse强制转换,否则将强制转换异常抛出

如何在不向DeleteShipmentResponse进行类型转换的情况下获取此信息? 我必须使用通用接口吗

感谢您的帮助

如果所有IResponse都可以使用无参数构造函数,您可以将IResponse自身设置为泛型,即T约束为IResponse:

如果所有IResponse都可以使用无参数构造函数,则可以将IResponse自身设置为泛型,即T约束为IResponse:


为什么类X中名为SetYX的东西返回X?为什么不使用ResponseFactory.CreateResponseint代码、字符串标题、字符串[]错误。。。为什么不只是简单的公共响应{int ErrorCode{get;set;}bool Success…其他一些常见的道具…公共T数据{get;set;}在这种情况下,我看不到工厂的好处。你可以删除工厂类,无论你在哪里调用ResponseFactory.CreateDeleteResponse,只要调用new DeleteResponse即可。如果你这样做,你问题的本质仍然会保留,这表明工厂类不是你问题的核心。它是模糊的g问题。即使你把它保留在代码中,我也会把它从问题中删除,因为它不相关,而且更难理解。@ScottHannen你是对的,我想我喜欢把我的生活复杂化^^。我不知道我为什么要这样做。这是我们要做的。为什么类X中名为SetYX的东西返回X?为什么你不只使用ResponseFactory.CreateResponseint代码,字符串标题,字符串[]错误?…为什么不只是简单的公共响应{int ErrorCode{get;set;}布尔成功…其他一些常见的道具…公共T数据{get;set;}在这种情况下,我看不到工厂的好处。你可以删除工厂类,无论你在哪里调用ResponseFactory.CreateDeleteResponse,只要调用new DeleteResponse即可。如果你这样做,你问题的本质仍然会保留,这表明工厂类不是你问题的核心。它是模糊的g问题。即使你将其保留在代码中,我也会将其从问题中删除,因为它与问题无关,并且使问题更难理解。@ScottHannen你是对的,我想我喜欢将我的生活复杂化。^^^。我不知道我为什么要这样做。这是我们所做的。@JulienMartin很乐意提供帮助!如果答案对你有效,请将其标记为接受概述的检查在答案的左边打上记号;@JulienMartin很乐意帮忙!如果答案对你有效,请在答案左边打上勾选标记,表示接受;
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
        };
    }
}