Рассмотрим следующие два контракта данных:
[DataContract]
public class Item
{
[DataMember]
public int X;
}
[DataContract]
public class SubItem : Item
{
[DataMember]
public int Y;
}
В чем разница между использованием двух контрактов данных в следующих контрактах на обслуживание.
[ServiceContract]
public interface IInterface
{
[OperationContract]
[ServiceKnownType(typeof(SubItem))]
void Save(Item i);
}
[ServiceContract]
public interface IInterface
{
[OperationContract]
void Save(SubItem i);
}
Может ли первый быть вызван с подклассом предмета, отличного от SubItem? Если да, то что означает значение ServiceKnownType?
Когда вы используете для первого случая, когда SubItem
from Item
вы SubItem
сервису, когда он раскрывает его WSDL, SubItem
десериализацию типа SubItem
поскольку он может использоваться в качестве аргумента для параметра Item
(принципал полиморфизма) в противном случае конечные точки получателя не смогут передать SubItem в качестве аргумента для метода, даже если тип был десериализован на стороне клиента с помощью DataMemberAttribute
.
Note
что при применении ServiceKnownType
класс будет сериализован, даже если SubItem
не был отмечен DataMember
здесь пример
Сфера обслуживания
using System.Runtime.Serialization;
using System.ServiceModel;
namespace WcfService1
{
[ServiceContract]
public interface IService1
{
[OperationContract]
[ServiceKnownType(typeof(SubItem))] // try to comment this and uncomment GetDataUsingDataContract
Item GetData(int value);
//[OperationContract] //here try to comment/uncomment and see if the subitem was deserialized at client side the operation on server side will not be executed
//Item GetDataUsingDataContract(SubItem item);
//// TODO: Add your service operations here
}
// Use a data contract as illustrated in the sample below to add composite types to service operations.
[DataContract]
public class Item
{
bool boolValue = true;
string stringValue = "Hello ";
[DataMember]
public bool BoolValue
{
get { return boolValue; }
set { boolValue = value; }
}
[DataMember]
public string StringValue
{
get { return stringValue; }
set { stringValue = value; }
}
}
//[DataContract]
public class SubItem:Item
{
private string _subItemVersion;
//[DataMember]
public string SubItemToStringValueVersion { get { return _subItemVersion; } set { _subItemVersion = value; } }
}
}
Сторона клиента
static void Main(string[] args)
{
Service1Client service1Client = new Service1Client();
var result = service1Client.GetData(5);
if (result is SubItem)
{
}
}
В чем разница между использованием двух контрактов данных в следующих контрактах на обслуживание? С первым вы можете передать объект типа Item или SubItem, поскольку SubItem отображается как KnownType. Во втором вы можете передавать только элементы SubItem.
Может ли первый быть вызван с подклассом предмета, отличного от SubItem? Если да, то что означает значение ServiceKnownType? Нет, он не может быть вызван с подклассом предмета, кроме SubItem. Чтобы иметь возможность сделать это, вам придется выставить его как KnownType.
Да, первый может быть вызван, но если фактический тип неизвестен службе, он может использовать только те элементы, которые находятся в типе Item.
В этом случае ServiceKnownType не имеет смысла/смысла для сервера, потому что он не используется ни в параметрах, ни в возвращаемых типах.
Например, если операция сохранения вернет элемент, а фактическим элементом будет SubItem, он сериализует результат как SubItem. Для этого атрибут ServiceKnownType.
Первый метод Save может быть вызван только с экземпляром Item или SubItem, но второй принимает только экземпляр SubItem.
Цель ServiceKnownTypeAttribute - указать типы, которые должны быть включены для рассмотрения во время десериализации. Дополнительные сведения см. В разделе " Известные типы данных" и " ServiceKnownTypeAttribute"