C#(Web API)依赖项注入(带Unity)返回类型接口

C#(Web API)依赖项注入(带Unity)返回类型接口,c#,asp.net-web-api,interface,controller,datacontractserializer,C#,Asp.net Web Api,Interface,Controller,Datacontractserializer,我正在用ASP.NET构建一个WebApi。现在,我将整个应用程序划分为几个层,其中两层是“接口”和“模型”(每个层都有自己的.dll)。在“models.dll”中,定义了我的所有模型,并在应用程序启动时将它们注入需要的地方。到现在为止,一直都还不错。现在,当我从控件返回值时,我面临一个问题。让我们假设如下: public class TestController : ApiController { IBusinessObject _businessObject; publi

我正在用ASP.NET构建一个WebApi。现在,我将整个应用程序划分为几个层,其中两层是“接口”和“模型”(每个层都有自己的.dll)。在“models.dll”中,定义了我的所有模型,并在应用程序启动时将它们注入需要的地方。到现在为止,一直都还不错。现在,当我从控件返回值时,我面临一个问题。让我们假设如下:

public class TestController : ApiController
{
    IBusinessObject _businessObject;

    public TestController(IBusinessObject businessObject)
    {
        this._businessObject= businessObject;
    }

    [Route("details/object/{id}")]
    [HttpGet]
    public ISomeObject GetObjectByNr(int id)
    {   
        return  this._businessObject.SearchForObject(id);
    }
}
现在,当您查看GetObjectByNr时,您可以看到它的返回类型是
ISomeObject
(当然,它的返回类型也是。\u businessObject.SearchForObject(id)也是ISomeObject)。ISomeObject的实际实现在ModelLayer内部,但我不想将其包括在我的WebApi项目中,因为它只能通过接口进行通信。现在,当我像这样运行它时,我得到一个错误,它说我应该使用
DataContractResolver
(以及一些关于序列化的内容)。我知道我无法序列化接口,但我认为我的应用程序足够聪明,可以在这里找到合适的类来注入(在开始时,我确实解析了所有接口,并且在调用
this.\u businessObject.SearchForObject(id)时工作得很好)
调用了正确的类并用正确的值填充,但就在此时返回对象时,我发现了错误)。我一直在研究SO,发现了一些“方法”,例如
KnownType(typeof(SomeObject))
属性。但当我试图在TestController内部设置时,它并没有被识别(但即使这样做可行,它也需要对我的实际模型类的引用,我不希望这样)

有没有办法使我的接口可序列化,并返回正确的对象,而不告诉我的控制器ISomeObject的实现是什么

谢谢

编辑:

尝试使用您自己的
MediaTypeFormatter
。您可以使用sharpSerializer或Json.NET。有关如何执行此操作的信息,请参见:

编辑说明:下面的代码针对的是MVC控制器,而不是WebAPI ApicController

如果您没有绑定到
DataContractSerializer
,那么可以使用其他一些方法,比如json序列化。例如,您可以使用Json.NET。最方便的方法是覆盖默认的Json结果行为:

public class JsonNetResult : JsonResult
{

    public JsonSerializerSettings SerializerSettings { get; set; }
    public Formatting Formatting { get; set; }

    public JsonNetResult()
    {
        Formatting = Formatting.None;
        SerializerSettings = new JsonSerializerSettings();
        JsonRequestBehavior = JsonRequestBehavior.DenyGet;
    }

    public override void ExecuteResult(ControllerContext context)
    {
        if (context == null)
            throw new ArgumentNullException("context");

        if (JsonRequestBehavior == JsonRequestBehavior.DenyGet
            && String.Equals(context.HttpContext.Request.HttpMethod, "GET", StringComparison.OrdinalIgnoreCase))
        {
            throw new InvalidOperationException("This request has been blocked because sensitive information could be disclosed to third party web sites when this is used in a GET request. To allow GET requests, set JsonRequestBehavior to AllowGet.");
        }

        HttpResponseBase response = context.HttpContext.Response;

        response.ContentType = !string.IsNullOrEmpty(ContentType)
                                    ? ContentType
                                    : "application/json";

        if (ContentEncoding != null)
            response.ContentEncoding = ContentEncoding;

        if (Data != null)
        {
            var writer = new JsonTextWriter(response.Output) { Formatting = Formatting };

            var serializer = JsonSerializer.Create(SerializerSettings);
            serializer.Serialize(writer, Data);

            writer.Flush();
        }
    }
然后在控制器类中重写Json方法:

    protected override JsonResult Json(object data, string contentType, System.Text.Encoding contentEncoding)
    {
        return new JsonNetResult
        {
            ContentType = contentType,
            ContentEncoding = contentEncoding,
            Data = data
        };
    }

    protected override JsonResult Json(object data, string contentType, System.Text.Encoding contentEncoding, JsonRequestBehavior behavior)
    {
        return new JsonNetResult
        {
            ContentType = contentType,
            ContentEncoding = contentEncoding,
            Data = data,
            JsonRequestBehavior = behavior
        };
    }
然后像这样使用它:

public ActionResult GetObjectByNr(int id)
{   
    return  Json(this._businessObject.SearchForObject(id), JsonRequestBehavior.AllowGet);
}

您是否可以发布您得到的确切错误/异常,没有无法序列化接口的内在原因,想想有多少控制器操作返回
IEnumerable
。接口不可序列化。它们只是一个对象实现的契约。也许我的措辞不准确,但是你可以序列化一个实现接口的对象,而不必知道任何关于实现的信息。例外是德语。这就是为什么我没有发布它的原因。它仍然会帮助您吗?但是当客户机需要一个xml作为响应时,这是行不通的?这是行不通的。即使我包含NewtonSoft.JSON,JsonResult也不会被识别,JSON当然不是XML。如果您需要XML,可以使用sharpSerializer()。我的意思是,使用这种方法,我正在失去这种灵活性(现在客户机可以请求XML和json)。所以当我使用intefaces作为返回类型时,控制器没有办法表现“正常”的行为?(所以我必须通过编程来处理每种输出类型)你是对的,在我的回答中,我的目标是MVC控制器,而不是WebAPI ApicController。对不起,弄错了。但是,您可以在以下教程中使用自定义序列化程序: