为什么在 web api 方法中返回接口时,我用接口值获取继承类的值
本文关键字:接口 获取 继承 web api 方法 返回 为什么 | 更新日期: 2023-09-27 18:37:19
>我有一个从接口继承的类,并且我从我的 web api 返回接口得到 methed,问题是我正在获取继承类的值作为 json 字符串。
这是界面
public interface IFoo
{
string A { get ;set ; }
string B { get ; set ; }
}
继承的类
public class Child : iFoo
{
string A { get ; set ; }
string B { get ; set ; }
string C { get ; set ; }
string D { get ; set ; }
}
然后我从控制器的 GetMethod 返回 IFoo
public IFoo GetIFoo()
{
return ChildInstance ;
}
当前结果给了我继承类的所有值,以及两个接口,但我只想要在 json 结果中的接口中实现的值。
当它命中 Json 序列化程序时,它并不关心方法的返回类型是什么。它只知道"我有这个对象,让我们看看我能用它做什么"。
如果希望序列化程序仅包含接口具有的属性,则最好为其指定一个仅具有接口具有的属性的对象。例如,您可以考虑使用自动映射器将值从ChildInstance
复制到此新对象。
另一种方法更复杂 - 实现自己的序列化程序,以便 Json 序列化程序没有机会参与其中。
您的方法被收缩为返回实现IFoo
的对象。它可以返回任何实现IFoo
的对象,但不能返回Ifoo
本身,因为你不能有一个接口的实例。所以它返回一个实例 Child
.
然后,JSON 序列化程序将获得此Child
实例,并使用反射来确定其属性。它找到A - D
并因此对其进行序列化。
如果您只想A - B
序列化,则必须返回仅实现 A - B
的类的实例。
说了这么多,如果你使用的是ASP MVC,那么请查看 http://www.creave.dk/post/2009/10/07/Excluding-properties-from-being-serialized-in-ASPNET-MVC-JsonResult.aspx。通过将类定义更改为
public class Child : iFoo
{
string A { get ; set ; }
string B { get ; set ; }
[ScriptIgnore]
string C { get ; set ; }
[ScriptIgnore]
string D { get ; set ; }
}
然后,您已指示 JSON 序列化程序仅序列化A - B
。
如果您不介意返回动态,则可以执行以下操作:
另一方面,如果您使用 json 序列化程序,这只能开箱即用,因此您必须指定"accept: application/json"才能正常工作。
public class Person
{
public string Name { get; set; }
}
public class User : Person
{
public string Title { get; set; }
public string Email { get; set; }
}
public dynamic Get()
{
var user = new User { Title = "Developer", Email = "foo@bar.baz", Name = "MyName" };
return new { user.Name, user.Email };
}
如果控制器方法的返回类型是接口,还可以应用操作筛选器以仅序列化接口属性。这样,您始终与接口定义保持同步,而无需更改实现接口的类上的任何属性。
为此,您首先必须创建自定义InterfaceContractResolver
协定解析器,如下所述:
public class InterfaceContractResolver : DefaultContractResolver
{
private readonly Type _interfaceType;
public InterfaceContractResolver(Type interfaceType)
{
_interfaceType = interfaceType;
}
protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization)
{
IList<JsonProperty> properties = base.CreateProperties(_interfaceType, memberSerialization);
return properties;
}
}
然后添加一个操作筛选器(作为此处所述的属性,或者全局,如果您希望将其作为默认行为),该筛选器查看控制器方法的返回类型,并且它是使用上面定义的协定解析程序的接口:
public class InterfaceFilterAttribute : ActionFilterAttribute
{
public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext)
{
ObjectContent content = actionExecutedContext.Response.Content as ObjectContent;
if (content != null)
{
Type returnType = actionExecutedContext.ActionContext.ActionDescriptor.ReturnType;
if (returnType.IsInterface && content.Formatter is JsonMediaTypeFormatter)
{
var formatter = new JsonMediaTypeFormatter
{
SerializerSettings =
{
ContractResolver = new InterfaceContractResolver(returnType)
}
};
actionExecutedContext.Response.Content = new ObjectContent(content.ObjectType, content.Value, formatter);
}
}
}
}