Frage

Ich versuche, einen bekannten Typ in meiner config angeben, aber ich habe Probleme mit der Tatsache haben, dass sie von Object ableitet. Ich kann es funktioniert die bekannte Art über Attribut angeben. Aber in diesem Fall muss ich es aus der Config zu arbeiten.

Hier ist ein Beispiel. Die folgende funktioniert gut:

[ServiceContract]
[ServiceKnownType(typeof(MyData))]
public interface IContract
{
    [OperationContract]
    void Send(object data);
}

[DataContract]
public class MyData
{
    [DataMember]
    public string Message { get; set; }
}

Aber wenn ich das ServiceKnownType Attribut entfernen und die folgende in der Config setzen:

<system.runtime.serialization>
  <dataContractSerializer>
    <declaredTypes>
      <add type="System.Object, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
        <knownType type="WpfApplication1.MyData, WpfApplication1, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"/>
      </add>
    </declaredTypes>
  </dataContractSerializer>
</system.runtime.serialization>

ich eine Configuration mit der Meldung „Der Wert für die Eigenschaft‚Typ‘ist nicht gültig Der Fehler ist:.. Der Typ System.Object nicht als deklarierte Typ in Config verwendet werden können“

Gibt es trotzdem, diese Arbeit über Config zu machen?

War es hilfreich?

Lösung

Die Antwort stellt sich heraus, um es nicht möglich ist, zu tun, was ich in der Config-Datei allein tun will. Die Konfigurations oben entspricht dem [Knowntype] -Attribut auf Datacontracts verwendet. Es scheint keine Möglichkeit zu geben [ServiceKnownType] zu implementieren in der config.

Ein alternativer Ansatz ist [ServiceKnownType (methoden, Typ)] Attribut mit einem benutzerdefinierten Konfigurationsabschnitt zu verwenden. Die neue Konfiguration sieht wie folgt aus:

<configuration>
  <configSections>
    <section
      name="serviceKnownTypes"
      type="WpfApplication1.ServiceKnownTypesSection, WpfApplication1, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"/>
  </configSections>
  <serviceKnownTypes>
    <declaredServices>
      <serviceContract type="WpfApplication1.IContract, WpfApplication1, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null">
        <knownTypes>
          <knownType type="WpfApplication1.MyData, WpfApplication1, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"/>
        </knownTypes>
      </serviceContract>
    </declaredServices>
  </serviceKnownTypes>
</configuration>

Die Verträge:

[ServiceContract]
[ServiceKnownType("GetServiceKnownTypes", typeof(KnownTypeHelper))]
public interface IContract
{
    [OperationContract]
    void Send(object data);
}

[DataContract]
public class MyData
{
    [DataMember]
    public string Message { get; set; }
}

Die Helfer-Klasse, die den Rückruf, dass gibt die Liste der bekannten Typen enthält

public static class KnownTypeHelper
{
    public static IEnumerable<Type> GetServiceKnownTypes(ICustomAttributeProvider provider)
    {
        List<Type> result = new List<Type>();

        ServiceKnownTypesSection serviceKnownTypes = (ServiceKnownTypesSection)ConfigurationManager.GetSection("serviceKnownTypes");
        DeclaredServiceElement service = serviceKnownTypes.Services[((Type)(provider)).AssemblyQualifiedName];

        foreach (ServiceKnownTypeElement knownType in service.KnownTypes)
        {
            result.Add(knownType.Type);
        }

        return result;
    }
}

Informationen zum Erstellen von Abschnitten benutzerdefinierte Konfiguration können hier gefunden werden:

http://msdn.microsoft.com/en-us/library/ 2tw134k3.aspx

http://msdn.microsoft.com/en- us / library / system.configuration.configurationcollectionattribute.aspx

Andere Tipps

Ich bin mir nicht sicher, ob es durch Design, aber die KnownTypeHelper unten keinen Fehler auslösen, wenn Sie noch nicht einen Servicevertrag mit bekannten Typen erklärt. (Das heißt seine optional bekannte Arten zu Serviceverträgen hinzuzufügen).

using System;
using System.Collections.Generic;
using System.Configuration;
using System.Reflection;

/// <summary>
/// Helper for finding the known types for Wcf Services from a configuration file.
/// </summary>
public static class KnownTypeHelper
{
    /// <summary>
    /// Gets the known types for the service from a configuration file.
    /// </summary>
    /// <param name="provider">
    /// The provider.
    /// </param>
    /// <returns>
    /// The known types for the service from a configuration file.
    /// </returns>
    public static IEnumerable<Type> GetServiceKnownTypes(ICustomAttributeProvider provider)
    {
        var result = new List<Type>();

        var serviceKnownTypes = (ServiceKnownTypesSection)ConfigurationManager.GetSection("serviceKnownTypes");
        if (serviceKnownTypes != null)
        {
            var service = serviceKnownTypes.Services[((Type)provider).AssemblyQualifiedName];

            if (service != null)
            {
                foreach (ServiceKnownTypeElement knownType in service.KnownTypes)
                {
                    result.Add(knownType.Type);
                }
            }
        }

        return result;
    }
}

Um jemand anderes die Mühe der Erstellung der Konfigurationsklassen zu speichern,

Hinweis: Es gibt keine Validierung der Montage qualifizierten Typnamen. Wenn jemand will, die sachgemäßen Attribute hinzufügen, dies zu tun, bitte.

using System.Configuration;

/// <summary>
/// Section for configuration known types for services.
/// </summary>
public class ServiceKnownTypesSection : ConfigurationSection
{
    /// <summary>
    /// Gets services.
    /// </summary>
    [ConfigurationProperty("declaredServices", IsDefaultCollection = false)]
    [ConfigurationCollection(typeof(DeclaredServiceElement), AddItemName = "serviceContract", CollectionType = ConfigurationElementCollectionType.AddRemoveClearMap)]
    public DeclaredServiceElementCollection Services
    {
        get
        {
            return (DeclaredServiceElementCollection)base["declaredServices"];
        }
    }
}

/// <summary>
/// Collection of declared service elements.
/// </summary>
public class DeclaredServiceElementCollection : ConfigurationElementCollection
{
    /// <summary>
    /// Gets the service for which known types have been declared for.
    /// </summary>
    /// <param name="key">
    /// The key of the service.
    /// </param>
    public new DeclaredServiceElement this[string key]
    {
        get
        {
            return (DeclaredServiceElement)BaseGet(key);
        }

        set
        {
            var element = BaseGet(key);
            var index = this.BaseIndexOf(element);
            if (BaseGet(index) != null)
            {
                BaseRemoveAt(index);
            }

            BaseAdd(index, value);
        }
    }

    /// <summary>
    /// When overridden in a derived class, creates a new <see cref="T:System.Configuration.ConfigurationElement"/>.
    /// </summary>
    /// <returns>
    /// A new <see cref="T:System.Configuration.ConfigurationElement"/>.
    /// </returns>
    protected override ConfigurationElement CreateNewElement()
    {
        return new DeclaredServiceElement();
    }

    /// <summary>
    /// Gets the element key for a specified configuration element when overridden in a derived class.
    /// </summary>
    /// <returns>
    /// An <see cref="T:System.Object"/> that acts as the key for the specified <see cref="T:System.Configuration.ConfigurationElement"/>.
    /// </returns>
    /// <param name="element">
    /// The <see cref="T:System.Configuration.ConfigurationElement"/> to return the key for. 
    /// </param>
    protected override object GetElementKey(ConfigurationElement element)
    {
        return ((DeclaredServiceElement)element).Type;
    }
}

/// <summary>
/// The service for which known types are being declared for.
/// </summary>
public class DeclaredServiceElement : ConfigurationElement
{
    /// <summary>
    /// Gets or sets Type.
    /// </summary>
    [ConfigurationProperty("type", IsRequired = true, IsKey = true)]
    public string Type
    {
        get
        {
            return (string) this["type"];
        }

        set
        {
            this["type"] = value;
        }
    }

    /// <summary>
    /// Gets KnownTypes.
    /// </summary>
    [ConfigurationProperty("knownTypes", IsDefaultCollection = false)]
    [ConfigurationCollection(typeof(DeclaredServiceElement), AddItemName = "knownType", CollectionType = ConfigurationElementCollectionType.AddRemoveClearMap)]
    public ServiceKnownTypeElementCollection KnownTypes
    {
        get
        {
            return (ServiceKnownTypeElementCollection)base["knownTypes"];
        }
    }
}

/// <summary>
/// A collection of known type elements.
/// </summary>
public class ServiceKnownTypeElementCollection : ConfigurationElementCollection
{
    /// <summary>
    /// Gets an known type with the specified key.
    /// </summary>
    /// <param name="key">
    /// The key of the known type.
    /// </param>
    public new ServiceKnownTypeElement this[string key]
    {
        get
        {
            return (ServiceKnownTypeElement)BaseGet(key);
        }

        set
        {
            var element = BaseGet(key);
            var index = this.BaseIndexOf(element);
            if (BaseGet(index) != null)
            {
                BaseRemoveAt(index);
            }

            BaseAdd(index, value);
        }
    }

    /// <summary>
    /// When overridden in a derived class, creates a new <see cref="T:System.Configuration.ConfigurationElement"/>.
    /// </summary>
    /// <returns>
    /// A new <see cref="T:System.Configuration.ConfigurationElement"/>.
    /// </returns>
    protected override ConfigurationElement CreateNewElement()
    {
        return new ServiceKnownTypeElement();
    }

    /// <summary>
    /// Gets the element key for a specified configuration element when overridden in a derived class.
    /// </summary>
    /// <returns>
    /// An <see cref="T:System.Object"/> that acts as the key for the specified <see cref="T:System.Configuration.ConfigurationElement"/>.
    /// </returns>
    /// <param name="element">
    /// The <see cref="T:System.Configuration.ConfigurationElement"/> to return the key for. 
    /// </param>
    protected override object GetElementKey(ConfigurationElement element)
    {
        return ((ServiceKnownTypeElement)element).Type;
    }
}

/// <summary>
/// Configuration element for a known type to associate with a service.
/// </summary>
public class ServiceKnownTypeElement : ConfigurationElement
{
    /// <summary>
    /// Gets or sets TypeString.
    /// </summary>
    [ConfigurationProperty("type", IsRequired = true, IsKey = true)]
    public string TypeString
    {
        get
        {
            return (string)this["type"];
        }

        set
        {
            this["type"] = value;
        }
    }

    /// <summary>
    /// Gets or sets Type.
    /// </summary>
    public Type Type
    {
        get
        {
            return Type.GetType(this.TypeString);
        }

        set
        {
            this["type"] = value.AssemblyQualifiedName;
        }
    }
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top