DataContract Yedeği
DataContract örneği, serileştirme, seri durumdan çıkarma, şema dışarı aktarma ve şema içeri aktarma gibi işlemlerin bir veri sözleşmesi vekil sınıfı kullanılarak nasıl özelleştirilebileceğini gösterir. Bu örnek, bir istemci ve sunucu senaryosunda verilerin seri hale getirildiği ve bir Windows Communication Foundation (WCF) istemcisi ile hizmeti arasında iletildiği bir vekilin nasıl kullanılacağını gösterir.
Not
Bu örnek için kurulum yordamı ve derleme yönergeleri bu konunun sonunda yer alır.
Örnek aşağıdaki hizmet sözleşmesini kullanır:
[ServiceContract(Namespace = "http://Microsoft.ServiceModel.Samples")]
[AllowNonSerializableTypes]
public interface IPersonnelDataService
{
[OperationContract]
void AddEmployee(Employee employee);
[OperationContract]
Employee GetEmployee(string name);
}
bu AddEmployee
işlem, kullanıcıların yeni çalışanlar hakkında veri eklemesine olanak tanır ve GetEmployee
işlem, ad temelinde çalışanları aramayı destekler.
Bu işlemler aşağıdaki veri türünü kullanır:
[DataContract(Namespace = "http://Microsoft.ServiceModel.Samples")]
class Employee
{
[DataMember]
public DateTime dateHired;
[DataMember]
public Decimal salary;
[DataMember]
public Person person;
}
Employee
türünde, Person
sınıfı (aşağıdaki örnek kodda gösterilmiştir) geçerli bir veri sözleşmesi sınıfı olmadığından tarafından DataContractSerializer serileştirilemez.
public class Person
{
public string firstName;
public string lastName;
public int age;
public Person() { }
}
özniteliğini sınıfına DataContractAttributePerson
uygulayabilirsiniz, ancak bu her zaman mümkün değildir. Örneğin, sınıfı üzerinde Person
denetiminiz olmayan ayrı bir derlemede tanımlanabilir.
Bu kısıtlama göz önüne alındığında, sınıfı seri hale getirmenin Person
bir yolu, sınıfı ile işaretlenmiş başka bir sınıfla DataContractAttribute değiştirmek ve gerekli verileri yeni sınıfa kopyalamaktır. Amaç, sınıfının içinde DataContract olarak görünmesini sağlamaktır Person
DataContractSerializer. Bunun, veri olmayan anlaşma sınıflarını seri hale getirmenin bir yolu olduğunu unutmayın.
Örnek mantıksal olarak sınıfını Person
adlı PersonSurrogated
farklı bir sınıfla değiştirir.
[DataContract(Name="Person", Namespace = "http://Microsoft.ServiceModel.Samples")]
public class PersonSurrogated
{
[DataMember]
public string FirstName;
[DataMember]
public string LastName;
[DataMember]
public int Age;
}
Bu değişikliği gerçekleştirmek için veri sözleşmesi vekili kullanılır. Veri sözleşmesi vekili, uygulayan IDataContractSurrogatebir sınıftır. Bu örnekte sınıfı bu AllowNonSerializableTypesSurrogate
arabirimi uygular.
Arabirim uygulamasında, ilk görev ile Person
PersonSurrogated
arasında bir tür eşlemesi oluşturmaktır. Bu hem serileştirme zamanında hem de şema dışarı aktarma zamanında kullanılır. Bu eşleme yöntemi uygulanarak GetDataContractType(Type) elde edilir.
public Type GetDataContractType(Type type)
{
if (typeof(Person).IsAssignableFrom(type))
{
return typeof(PersonSurrogated);
}
return type;
}
yöntemi, GetObjectToSerialize(Object, Type) aşağıdaki örnek kodda gösterildiği gibi serileştirme sırasında bir örneği bir PersonSurrogated
örneğe eşlerPerson
.
public object GetObjectToSerialize(object obj, Type targetType)
{
if (obj is Person)
{
Person person = (Person)obj;
PersonSurrogated personSurrogated = new PersonSurrogated();
personSurrogated.FirstName = person.firstName;
personSurrogated.LastName = person.lastName;
personSurrogated.Age = person.age;
return personSurrogated;
}
return obj;
}
yöntemi, GetDeserializedObject(Object, Type) aşağıdaki örnek kodda gösterildiği gibi seri durumdan çıkarma için ters eşleme sağlar.
public object GetDeserializedObject(object obj,
Type targetType)
{
if (obj is PersonSurrogated)
{
PersonSurrogated personSurrogated = (PersonSurrogated)obj;
Person person = new Person();
person.firstName = personSurrogated.FirstName;
person.lastName = personSurrogated.LastName;
person.age = personSurrogated.Age;
return person;
}
return obj;
}
Şema içeri aktarma sırasında veri sözleşmesini PersonSurrogated
mevcut Person
sınıfla eşlemek için örnek, aşağıdaki örnek kodda gösterildiği gibi yöntemini uygular GetReferencedTypeOnImport(String, String, Object) .
public Type GetReferencedTypeOnImport(string typeName,
string typeNamespace, object customData)
{
if (
typeNamespace.Equals("http://schemas.datacontract.org/2004/07/DCSurrogateSample")
)
{
if (typeName.Equals("PersonSurrogated"))
{
return typeof(Person);
}
}
return null;
}
Aşağıdaki örnek kod arabiriminin IDataContractSurrogate uygulamasını tamamlar.
public System.CodeDom.CodeTypeDeclaration ProcessImportedType(
System.CodeDom.CodeTypeDeclaration typeDeclaration,
System.CodeDom.CodeCompileUnit compileUnit)
{
return typeDeclaration;
}
public object GetCustomDataToExport(Type clrType,
Type dataContractType)
{
return null;
}
public object GetCustomDataToExport(
System.Reflection.MemberInfo memberInfo, Type dataContractType)
{
return null;
}
public void GetKnownCustomDataTypes(
KnownTypeCollection customDataTypes)
{
// It does not matter what we do here.
throw new NotImplementedException();
}
Bu örnekte, vekil ServiceModel'de adlı AllowNonSerializableTypesAttribute
bir öznitelik tarafından etkinleştirilir. Geliştiricilerin bu özniteliği yukarıdaki hizmet sözleşmesinde gösterildiği gibi hizmet sözleşmelerine IPersonnelDataService
uygulaması gerekir. Bu öznitelik, ve yöntemlerindeki işlemlerde vekili ApplyClientBehavior
uygular IContractBehavior
ve ApplyDispatchBehavior
ayarlar.
Bu örnekte özniteliği gerekli değildir; bu örnekte gösterim amacıyla kullanılır. Kullanıcılar alternatif olarak, benzer IContractBehavior
IEndpointBehavior
bir öğesini el ile ekleyerek veya kod kullanarak ya da IOperationBehavior
yapılandırma kullanarak vekili etkinleştirebilir.
Uygulama, IContractBehavior
kayıtlı olup olmadığını DataContractSerializerOperationBehavior
denetleyerek DataContract kullanan işlemleri arar. Bunu yaparlarsa, özelliği bu davranışa DataContractSurrogate
ayarlar. Aşağıdaki örnek kod, bunun nasıl yapıldığını gösterir. Bu işlem davranışında vekilin ayarlanması, serileştirme ve seri durumdan çıkarma için etkinleştirir.
public void ApplyClientBehavior(ContractDescription description, ServiceEndpoint endpoint, System.ServiceModel.Dispatcher.ClientRuntime proxy)
{
foreach (OperationDescription opDesc in description.Operations)
{
ApplyDataContractSurrogate(opDesc);
}
}
public void ApplyDispatchBehavior(ContractDescription description, ServiceEndpoint endpoint, System.ServiceModel.Dispatcher.DispatchRuntime dispatch)
{
foreach (OperationDescription opDesc in description.Operations)
{
ApplyDataContractSurrogate(opDesc);
}
}
private static void ApplyDataContractSurrogate(OperationDescription description)
{
DataContractSerializerOperationBehavior dcsOperationBehavior = description.Behaviors.Find<DataContractSerializerOperationBehavior>();
if (dcsOperationBehavior != null)
{
if (dcsOperationBehavior.DataContractSurrogate == null)
dcsOperationBehavior.DataContractSurrogate = new AllowNonSerializableTypesSurrogate();
}
}
Meta veri oluşturma sırasında kullanılacak vekili takmak için ek adımlar atılması gerekir. Bunu yapmak için bir mekanizma, bu örneğin gösterdiği şeyi sağlamaktır IWsdlExportExtension
. Başka bir yol doğrudan değiştirmektir WsdlExporter
.
AllowNonSerializableTypesAttribute
özniteliği ve IContractBehavior
uygularIWsdlExportExtension
. Uzantı ya da IContractBehavior
IEndpointBehavior
bu durumda olabilir. Yöntem IWsdlExportExtension.ExportContract
uygulaması, DataContract için şema oluşturma sırasında kullanılana XsdDataContractExporter
ekleyerek vekili etkinleştirir. Aşağıdaki kod parçacığı bunun nasıl yapılacağını gösterir.
public void ExportContract(WsdlExporter exporter, WsdlContractConversionContext context)
{
if (exporter == null)
throw new ArgumentNullException("exporter");
object dataContractExporter;
XsdDataContractExporter xsdDCExporter;
if (!exporter.State.TryGetValue(typeof(XsdDataContractExporter), out dataContractExporter))
{
xsdDCExporter = new XsdDataContractExporter(exporter.GeneratedXmlSchemas);
exporter.State.Add(typeof(XsdDataContractExporter), xsdDCExporter);
}
else
{
xsdDCExporter = (XsdDataContractExporter)dataContractExporter;
}
if (xsdDCExporter.Options == null)
xsdDCExporter.Options = new ExportOptions();
if (xsdDCExporter.Options.DataContractSurrogate == null)
xsdDCExporter.Options.DataContractSurrogate = new AllowNonSerializableTypesSurrogate();
}
Örneği çalıştırdığınızda, istemci AddEmployee'yi ve ardından getEmployee çağrısını çağırarak ilk çağrının başarılı olup olmadığını denetler. GetEmployee işlem isteğinin sonucu istemci konsolu penceresinde görüntülenir. GetEmployee işleminin çalışanı bulmada başarılı olması ve "bulundu" yazdırması gerekir.
Not
Bu örnek seri hale getirmek, seri durumdan çıkarmak ve meta veri oluşturmak için bir vekilin nasıl eklenip eklenmek üzere yapıldığını gösterir. Meta verilerden kod oluşturma için bir vekilin nasıl bağlandığını göstermez. Bir vekilin istemci kodu oluşturma işlemine bağlanmak için nasıl kullanılabileceğini gösteren bir örnek görmek için bkz . Özel WSDL Yayını örneği.
Örneği ayarlamak, derlemek ve çalıştırmak için
Windows Communication Foundation Örnekleri için Tek Seferlik Kurulum Yordamı'nı gerçekleştirdiğinizden emin olun.
Çözümün C# sürümünü oluşturmak için Windows Communication Foundation Örnekleri Oluşturma başlığındaki yönergeleri izleyin.
Örneği tek veya makineler arası bir yapılandırmada çalıştırmak için Windows Communication Foundation Örneklerini Çalıştırma başlığındaki yönergeleri izleyin.