Aracılığıyla paylaş


DataContract Vekili

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.

Uyarı

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() { }
}

DataContractAttribute özniteliğini Person sınıfına uygulayabilirsiniz, ancak bu her zaman mümkün değildir. Örneğin, bu sınıf üzerinde Person denetiminiz olmayan ayrı bir bütünlemede tanımlanabilir.

Bu kısıtlama göz önüne alındığında, Person sınıfını seri hale getirmenin bir yolu, önce onu DataContractAttribute ile işaretlenmiş başka bir sınıfla değiştirmek ve ardından gerekli verileri yeni sınıfa kopyalamaktır. Amaç, Person sınıfının DataContractSerializer için bir DataContract olarak görünmesini sağlamaktır. Bunun, veri olmayan anlaşma sınıflarını seri hale getirmenin bir yolu olduğunu unutmayın.

Örnek, Person sınıfını mantıksal olarak PersonSurrogated adlı 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, IDataContractSurrogate arabirimini/şablonunu uygulayan bir sınıftır. Bu örnekte AllowNonSerializableTypesSurrogate sınıfı bu arabirimi uygular.

Arabirim uygulamasında, ilk görev Person ile 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, GetDataContractType(Type) yöntemi uygulanarak gerçekleştirilir.

public Type GetDataContractType(Type type)
{
    if (typeof(Person).IsAssignableFrom(type))
    {
        return typeof(PersonSurrogated);
    }
    return type;
}

Yöntem, serileştirme sırasında bir GetObjectToSerialize(Object, Type) örneğini bir Person örneğine eşleştirir, aşağıdaki örnek kodda gösterildiği gibi.

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;
}

Bu GetDeserializedObject(Object, Type) yöntemi, 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;
}

Veri sözleşmesini şema içeri aktarımı sırasında mevcut PersonSurrogated sınıfla eşlemek için Person yöntemi, aşağıdaki örnek kodda gösterildiği gibi uygulanır.

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 IContractBehavior uygular ve ApplyClientBehavior ile ApplyDispatchBehavior yöntemlerindeki işlemlerde vekili ayarlar.

Bu örnekte özniteliği gerekli değildir; bu örnekte gösterim amacıyla kullanılır. Kullanıcılar, yerine geçen bir öğeyi alternatif olarak, benzer bir IContractBehavior, IEndpointBehavior veya IOperationBehavior'yi el ile ekleyerek, kod kullanarak veya yapılandırma kullanarak etkinleştirebilir.

Uygulama, IContractBehavior kayıtlı olup olmadığını DataContractSerializerOperationBehavior denetleyerek DataContract kullanan işlemleri arar. Bunu yaparlarsa, DataContractSurrogate özelliği o davranışa ayarlar. Aşağıdaki örnek kod, bunun nasıl yapıldığını gösterir. Bu işlem davranışına vekilin ayarlanması, serileştirme ve seri durumdan çıkarma için etkinleştirilmesini sağlar.

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 yapmanın bir yolu, bu örneğin gösterdiği IWsdlExportExtension sağlamaktır. Başka bir yöntem, WsdlExporter öğesini doğrudan değiştirmektir.

AllowNonSerializableTypesAttribute özniteliği IWsdlExportExtension ve IContractBehavior'yi uygular. Uzantı, bu durumda ya bir IContractBehavior ya da bir IEndpointBehavior olabilir. Yöntem IWsdlExportExtension.ExportContract uygulaması, DataContract için şema oluşturma sırasında kullanılan XsdDataContractExporter'e vekili ekleyerek 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.

Uyarı

Bu örnek, serileştirme, serileştirmeden çıkarma ve meta veri oluşturma için bir vekilin nasıl eklendiğini 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çinOne-Time Kurulum Yordamını yaptığınızdan 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 bir makine veya makineler arası bir yapılandırmada çalıştırmak için, Windows Communication Foundation örneklerini çalıştırmayönergelerini izleyin.