如何设置return以便接受class1或class2?

时间:2013-07-17 07:59:11

标签: c# class

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

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;
        }
    }

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

更新

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

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

所以我不认为我可以抛出异常。我想返回一类文章,如果一切都好,所以我没有必要将我的数据转换为JSON,但如果出现问题,我想发送http代码500内部服务器错误到客户端。 我还没有阅读所有答案,但我想我必须在我的所有其他返回类中包含我的错误类,以便客户现在可以在出现问题时使用?

7 个答案:

答案 0 :(得分:10)

更新:

这可以让您更清楚地了解自己想要做什么。由于您不能抛出异常,因此您应该有一个基本结果类。我通常对我通过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,消息将为空。如果抛出异常,它将被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);
    }
}

答案 1 :(得分:8)

我会诚实地建议不要做你的建议。相反,要么使用现有的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);
    }
}

答案 2 :(得分:1)

如果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);
    }
}

答案 3 :(得分:1)

根据问题中的其他信息,由于这是一个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
        };
    }
}

答案 4 :(得分:0)

您可以尝试使用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;
    }

答案 5 :(得分:0)

其他答案处理的方式涉及如何使用接口和子类化来定义两个类的技术方法。

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

就个人而言,我会为你可能正在处理的错误类型创建一个新的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;             
    }
}

然后,调用者可以捕获异常并检查错误详细信息,代码与处理返回文章的代码保持分开。

答案 6 :(得分:-1)

我不确定你为什么要吞下这些exeptions,但是如果你这样做,那么这两种类型的返回类型是常见的。这两个类都继承自object,因此您可以将方法签名更改为public object function()