如何设置return,使其接受class1或class2

本文关键字:class1 class2 何设置 设置 return | 更新日期: 2023-09-27 18:22:38

在我的函数中,我如何开始填充它应该返回的类的参数,但如果发生异常,我将返回我的错误类?

public **** function()
    {
        try
        {
            Articles articles = new Articles();
            articles.articleid = 234;
            articles.articlename = "Milk";
            articles.deleted = 0;
            //continue fill Articles 
            //and an exception occurs

            return articles;
        }
        catch (Exception e)
        {
            Errors Error = new Errors();
            Error.exceptionmessage = e.Message;
            Error.exceptionname = e.ToString();
            Error.httpcode = 500;

            return Error;
        }
    }

这是可能的,也是一件好事吗?或者我应该用我的错误类扩展所有的返回类,即使我会用null值的分配返回很多信息。我想发送尽可能少的数据,如果我的功能失败,我只会发回错误。

更新

很抱歉没有提供足够的关于我的情况的信息,这是我想在网络服务中使用的功能

[OperationContract]
    [WebGet(
        ResponseFormat = WebMessageFormat.Json,
        RequestFormat = WebMessageFormat.Json)]
    **** Function();

所以我不认为我可以抛出一个例外。如果一切顺利,我想返回一类文章,这样我就不必将数据转换为JSON,但如果出现问题,我想向客户端发送http代码500内部服务器错误。我还没有阅读所有的答案,但我想我必须将我的错误类包括在所有其他返回类中,这样客户端现在就可以在出现问题时进行操作了?

如何设置return,使其接受class1或class2

更新:

这可以让你更深入地了解你想做什么。既然你不能抛出异常,你应该有一个基本的结果类。我通常对通过javascript调用的WCF方法这样做,因为它不能很好地处理异常。

所以你会想要一个像这样的基类

[DataContract]
public class AjaxResult
{
    public static AjaxResult GetSuccessResult()
    {
        return new AjaxResult();
    }
    [DataMember]
    public int Status { get; set; }
    [DataMember]
    public string Error { get; set; }
}

然后您可以继承它,添加您想要返回的任何数据。此示例返回单个产品对象和验证错误列表。

[DataContract]
public class SingleProductResult : AjaxResult
{
    [DataMember]
    public Product Data { get; set; }
    [DataMember]
    public IList<int> ValidationErrors { get; set; }
}

您还可以选择创建一个通用包装器,这样您就不必在方法中编写太多代码。我通常将其放在基类中,并让所有WCF服务从该类继承。

protected T PerformAjaxOperation<T>(Func<T> action) where T : AjaxResult, new()
{
    try
    {
        return action();
    }
    catch (AccessDeniedException ade)
    {
        // -- user tried to perform an invalid action
        return new T()
        {
            Status = AjaxErrorCodes.AccessDenied,
            Error = ade.ToString()
        };
    }
    catch (Exception ex)
    {
        return new T()
        {
            Error = ex.ToString(),
            Status = 1
        };
    }
}

那就这样用吧:

public SingleProductResult GetProduct(int productId)
{
    return PerformAjaxOperation(() =>
    {
        return retval = new SingleProductResult()
            {
                Data = ProductServiceInstance.GetProduct(productId)
            };
    });
}
public AjaxResult DeleteProduct(int productId)
{
    return PerformAjaxOperation(() => {
        ProductServiceInstance.DeleteProduct(productId);
        return AjaxResult.GetSuccessResult();
    });
}

所以,若一切顺利,错误将为0,消息将为null。如果抛出异常,则它将被PerformAjaxOperation()函数捕获,并填充在AjaxResult对象(或其派生对象)中,然后返回到客户端。


上一个答案:

我认为这不是个好主意。您可以通过创建从Exception继承的类来创建自定义异常,并在其中添加要保存的属性。然后,当异常发生时,您只需捕获它,并将其与其他细节一起放入这个新异常中。然后改为抛出此异常。然后,您可以在更高级别中捕获此异常并显示正确的消息。

一个例子:

public IList<Articles> GetArticles()
{
    try
    {
        return GetSomeArticlesFromDatabase();
    }
    catch (Exception innerException)
    {
        throw new MyCustomException("some data", 500, innerException);
    }
}
public class MyCustomException : Exception
{
    public int HttpCode { get; set; }
    public MyCustomException(string errorMessage, int httpCode, Exception innerException)
        : base(errorMessage, innerException) {
            HttpCode = httpCode;
    }
}
public void EntryPoint()
{
    try
    {
        DoSomething();
        var result = GetArticles();
        DoSomething();
        DisplayResult(result);
    }
    catch (MyCustomException ex)
    {
        ReturnHttpError(ex.Message, ex.HttpCode);
    }
}

我真诚地建议不要按照你的建议行事。相反,可以使用现有的Exception类型,也可以创建Exception的新子类并抛出它。如果需要,您甚至可以在新异常的InnerException中保留引起异常的信息。


但是,如果这种情况不能保证出现异常(您没有提供足够的有关正在执行的操作的详细信息),则可以创建一个包含错误/警告信息的Result类。不过,这种事情更适合作为警告。也就是说,它不是阻止事情继续的错误条件(异常),而是调用代码可以选择忽略的消息,而不会产生严重的副作用。

例如:

class Result<T>
{
    public Result(T Value, Errors Errors = null)
    {
        this.Value = Value;
        this.Errors = Errors;
    }
    public T Value {get; private set;}
    public Errors Errors {get; private set;}
}

用法(根据您的示例代码):

public Result<Articles> function()
{
    try
    {
        Articles articles = new Articles();
        articles.articleid = 234;
        articles.articlename = "Milk";
        articles.deleted = 0;
        //continue fill Articles 
        //and an exception occurs

        return new Result(articles);
    }
    catch (Exception e)
    {
        Errors Error = new Errors();
        Error.exceptionmessage = e.Message;
        Error.exceptionname = e.ToString();
        Error.httpcode = 500;

        return new Result<Articles>(null, Error);
    }
}

如果class1class2有一个公共的基类型或公共接口,请使用它。但在这种情况下,您可以创建一个包装器类来封装这两种结果类型,如下所示:

class MethodResult<T>
{
    public T Result { get; private set; }
    public Errors Errors { get; private set; }
    public MethodResult(T result) { this.Result = result; }
    public MethodResult(Errors errors) { this.Errors = errors; }
}
public MethodResult<Articles> MyMethod()
{
    try
    {
        ... 
        return new MethodResult<Articles>(articles);
    }
    catch(Exception e)
    {
        ... 
        return new MethodResult<Articles>(errors);
    }
}

根据问题中的其他信息,由于这是一个WCF服务,您可以抛出WebFaultException:

public Articles function()
{
    try
    {
        Articles articles = new Articles();
        articles.articleid = 234;
        articles.articlename = "Milk";
        articles.deleted = 0;
        //continue fill Articles 
        //and an exception occurs

        return articles;
    }
    catch (Exception e)
    {
        throw new WebFaultException(System.Net.HttpStatusCode.InternalServerError)
        {
            Message = e.Message
        };
    }
}

其他答案处理这一问题的方法涉及如何使用接口和子类定义这两个类的技术方法。

然而,从根本上说,你实际上是在解决错误的问题。您仍然需要在调用者中编写代码,以区分这两种类型的对象,并记录函数的工作方式。

就我个人而言,我会为您可能正在处理的错误类型创建一个新的Exception类,然后抛出它,例如:

public class InvalidArticleException: Exception {
    public string ExceptionMessage { get; set; }
    public string ExceptionName { get; set; }
    public int HttpCode { get; set; }
}
public **** function()
{
    try
    {
        // DO STUFF
        return articles;
    }
    catch (InvalidArgumentException e)
    {
        throw new InvalidArticleException() {
            ExceptionMessage = e.Message,
            ExceptionName = e.ToString(),
            HttpCode = 500
        }
    }
    catch (Exception ex) {   // Not actually required; left in for future debugging
       throw ex;             
    }
}

然后,调用方将能够捕获异常并检查其错误详细信息,代码与处理返回文章的代码保持分离。

您可以尝试out关键字,

public Articles function(out Error err)
    {
        Articles articles = null;
        err = null;
        try
        {
            articles = new Articles();
            articles.articleid = 234;
            articles.articlename = "Milk";
            articles.deleted = 0;
            // Set your article values
        }
        catch (Exception e)
        {
            Errors ex = new Errors();
            ex.exceptionmessage = e.Message;
            ex.exceptionname = e.ToString();
            ex.httpcode = 500;
            err = ex;
        }
        return articles;
    }

我不知道你为什么要接受这些exeption,但如果你这样做的话,这将使两种类型的返回类型都通用。这两个类都继承自对象,因此您可以将方法签名更改为public object function()