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 PersonDataContractSerializer. 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ı PersonSurrogatedfarklı 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 PersonPersonSurrogatedarası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ı AllowNonSerializableTypesAttributebir ö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 IContractBehaviorIEndpointBehavior 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 IContractBehavioruygularIWsdlExportExtension. Uzantı ya da IContractBehaviorIEndpointBehavior 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

  1. Windows Communication Foundation Örnekleri için Tek Seferlik Kurulum Yordamı'nı gerçekleştirdiğinizden emin olun.

  2. Çözümün C# sürümünü oluşturmak için Windows Communication Foundation Örnekleri Oluşturma başlığındaki yönergeleri izleyin.

  3. Ö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.